{"assessments":[],"deployments":[{"attestationHash":"9594244e8e5bafd4c86507ac11b531d4455daebc9735920dcd9fb3f3fe4ed5a8","chainId":11155111,"contracts":[{"address":"0x0457276d7b036818b3eddc1a4a3fceda61e9314d","blockNumber":11891109,"name":"Stacker","role":"other","txHash":"0x7a2d1e791756e5ce9a28408c8f141ccf6b669e824e54095d0328c31d364b9a60"},{"address":"0x3a3bfcb65614292b0ec7c62f9e3a5dac003b920e","blockNumber":11891109,"name":"ProjectRegistry","role":"other","txHash":"0x7a2d1e791756e5ce9a28408c8f141ccf6b669e824e54095d0328c31d364b9a60"}],"id":"9ee0316d-7266-4cf0-89aa-cff5f4f7610d","manifestHash":"2159a3217b47053f4a75eedaf8b9ea32c46a40b9e5cef51fcd5c5ce8e7e49311","status":"live"}],"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":"0b69e5bd-873f-4bcf-9e02-ef1a00a4b2f5","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"79abb0ffd0ffd59cb021977e1fcab4eb2bd863ae6f1b6b5b8f97a0c8972afc40","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"bccb0672a4076e14bbf0d98ebb9dee1a35b2bb9aaddb88ef7c4ff6e39f9a760a","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"972f534a7cb0e685a9fb596be93743fd8bbc1332ecf15479ab781572c4ff014f","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"b0a826cc4a7d66b9780eeb4014f03b6711c6da8b71d27a0c69accfc8ea97b716","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","tools":[]},"key":"audit_imported_code","kind":"code","role":"review","skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","state":"accepted"},{"acceptedSubmissionHash":"54cf370ab21deab26a1b6e6415576eef5f08c13cca871bd63b0c5bbded7c47e2","dependsOn":["adapt_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"413b11ad31703dc8665c567319603511d7173b9173c932ab4fed281171430ef9","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"2b34a4ba044caafd4b7de0fdd040cffc45ec02d8b5e01b7dededdc2405bce0d7","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"8e60751ee6a5d7d0ed8d3e88781d70e71bc7052f7ee2c64a1b393241d0d1f000","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"f4a978d3a9153226a2810e9e1c7d2c301524417a770a4a4500f4b1bd7a8e6853","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","state":"accepted"}],"objective":"Deploy two smart contracts on the Sepolia blockchain, the imd/acc Stacker and the imd/acc ProjectRegistry, then build a website for them. Their source, tests and launch.json are in github.com/khaed1/imd-acc (sepolia branch). What they do: a trading project calls credit(trader, amount) on the Stacker, which takes that much test IMD from the project and deposits it into the live TestSIMD staking vault in the trader's name, so the trader receives staked IMD as trading cashback (each project picks a rate from 0.25% to 1% of each trade), and it emits a Stacked event used for points. The ProjectRegistry decides which projects earn points: anyone applies or challenges, paying an IdentityMD oracle question through the Intake, and the oracle panel's signed yes or no lists or delists the project. Neither contract has an owner. They are wired to the TestIMD and TestSIMD contracts already live on Sepolia and to the IdentityMD Intake, which are reused, not redeployed. Steps: audit the imported code, adapt it to launch, an independent review, deploy both contracts on Sepolia, then a test website against the deployed addresses where a connected wallet can use the faucet, stack to itself, apply for or challenge a listing, and see its cashback, points and leaderboards.\n\nSepolia only (chainId 11155111). Launch kind evm_contracts with two contracts, the Stacker then the ProjectRegistry, as launch.json lists them. TestIMD 0x2b69099e59b05901faa1dd164fabf098bf831e82, TestSIMD 0xf9e2eec3b610ec6781f7438ac5fb4bc049d81cc1 and the Intake 0xa43e6f75ee006411f79ac1c84120606c2330de82 are live and reused. No owner or admin. GitHub publication is approved. Publishing the website at a public URL is approved; the platform publishes it from the release settings, so the website builders do not publish it themselves. Both contracts are deployed by the platform's launch, as usual.","parentJobId":null,"planHash":"42e56782ec62a980146184ff7782f01610af6255d8e91f3850119af0dd9effbf","previousHash":"b486da51f587aaf52870b08b5e7839a116fd7fc159034c72039ec1fc30d999e0","projectId":"0b69e5bd-873f-4bcf-9e02-ef1a00a4b2f5","publication":{"commit":"ef39dd18d1c65faaaa49c0a4a3f162960d594f18","deliveredAt":"2026-10-11T10:25:39.367Z","repoUrl":"https://github.com/identity-md-launches/launch-1294-deploy-two-smart-contracts"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[],"site":null,"snapshotHash":"3671e60286d7d96db895112fbd5c7c84e910e908f71cabe3eb0e3f09fd63ee1f","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"a4c81f495eb81dd0","findings":[{"citation":"resolved","description":"Area: Trust Gap (access x asymmetry between what proves an answer and what it is applied to). onOracleResult binds an answer to the registry only through the Intake's request id (projectOfIntake[intakeId]) and the signer check in _verifyAttestation. It never records a.requestId (the inherited `consumed` mapping and `_consume` are unused) and never compares a.questionHash with anything, so one signed attestation, obtained legitimately for one question, is also a valid, fully verified answer for every other open question of this registry asked within ISSUED_AT_TOLERANCE (5 minutes) of its issuedAt: a `yes` to project A's application lists project B, a `yes` to a challenge of A defends B and pays B's beneficiary the bond. The only gate between the two is the Intake writer's choice of `args` in `complete`, which the registry's own header lists as a trusted party; the oracle-consumer reference asks consumers to consume one of the two ids once, and the registry consumes the intake id, so this is defence in depth rather than a bypass for an outsider. It still means that a writer bug (an answer paired with the wrong request, which the writer's `args` can do with no on-chain check) or a replayed delivery turns into a listing, a delisting or a bond payment with no signed statement about that project. Minimal fix that preserves the design: call `_consume(a.requestId)` after `_verifyAttestation` (about 22k gas, within the 200k stipend measured by test/RegistryCallbackGas.t.sol), so each signed answer can act once; optionally also require a.questionHash to differ from the last one settled for the project.","line":297,"path":"src/ProjectRegistry.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ProjectRegistry, IIntake} from \"src/ProjectRegistry.sol\";\nimport {OracleAttestation} from \"src/oracle/OracleAttestation.sol\";\n\ncontract ReuseIMD is ERC20 {\n    constructor() ERC20(\"Identity.md (test)\", \"IMD\") {}\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\ncontract ReuseProject {}\n\n/// A minimal Intake v2 stand-in: pulls the price, records the callback, and lets the test play the\n/// writer, calling the recorded callback from the intake's own address under a gas stipend.\ncontract ReuseIntake is IIntake {\n    bytes32 public constant ACTION = \"oracle.request@oracle-1\";\n    uint256 public constant PRICE = 0.5e18;\n\n    struct Req {\n        address payer;\n        address target;\n        bytes4 selector;\n        bool completed;\n    }\n\n    mapping(bytes32 => Req) internal _reqs;\n    uint256 public count;\n\n    function priceOf(bytes32 action, address) external pure returns (uint256) {\n        return action == ACTION ? PRICE : 0;\n    }\n\n    function requestWithFailure(\n        bytes32 action,\n        bytes calldata,\n        Callback calldata callback,\n        bytes4,\n        address asset,\n        uint256 amount\n    ) external returns (bytes32 id) {\n        require(action == ACTION && amount >= PRICE, \"not sold\");\n        IERC20(asset).transferFrom(msg.sender, address(0x7EA5), amount);\n        id = keccak256(abi.encode(address(this), ++count));\n        _reqs[id] = Req(msg.sender, callback.target, callback.selector, false);\n    }\n\n    function requests(bytes32 id) external view returns (address, address, bytes4, bool) {\n        Req storage r = _reqs[id];\n        return (r.payer, r.target, r.selector, r.completed);\n    }\n\n    function deliver(\n        bytes32 id,\n        OracleAttestation.Attestation calldata a,\n        bytes calldata sig,\n        uint256 gasLimit\n    ) external returns (bool delivered) {\n        Req storage r = _reqs[id];\n        r.completed = true;\n        (delivered,) = r.target.call{gas: gasLimit}(abi.encodeWithSelector(r.selector, id, a, sig));\n    }\n}\n\n/// One signed attestation settles two different open requests: the registry keys replay on the\n/// Intake's id only and never consumes the oracle's `a.requestId`, so a signed answer obtained for\n/// one question is accepted again for any other open question of this registry (asked within\n/// ISSUED_AT_TOLERANCE of its issue) whenever the Intake's writer presents it.\ncontract AttestationReuseTest is Test {\n    uint256 internal constant SIGNER_KEY = 0xA11CE;\n\n    ReuseIntake internal intake;\n    ReuseIMD internal imd;\n    ProjectRegistry internal reg;\n    address internal applicant = makeAddr(\"applicant\");\n\n    function setUp() public {\n        vm.roll(1_000);\n        vm.warp(1_700_000_000);\n        intake = new ReuseIntake();\n        imd = new ReuseIMD();\n        reg = new ProjectRegistry(\n            address(intake), address(imd), address(0x57AC), vm.addr(SIGNER_KEY), 1, 5e18, 1 hours\n        );\n        imd.mint(applicant, 100e18);\n        vm.prank(applicant);\n        imd.approve(address(reg), type(uint256).max);\n    }\n\n    function test_sameSignedAnswerSettlesTwoRequests() public {\n        address p1 = address(new ReuseProject());\n        address p2 = address(new ReuseProject());\n        vm.startPrank(applicant);\n        bytes32 id1 = reg.applyListing(p1, \"One\", \"https://example.org/one\", 50, applicant);\n        bytes32 id2 = reg.applyListing(p2, \"Two\", \"https://example.org/two\", 50, applicant);\n        vm.stopPrank();\n\n        OracleAttestation.Attestation memory a;\n        a.requestId = bytes32(uint256(1) << 128);\n        a.chainId = 1;\n        a.questionHash = keccak256(\"question about p1\");\n        a.answerType = OracleAttestation.ANSWER_BOOL;\n        a.answer = abi.encode(true);\n        a.panelSize = 15;\n        a.quorum = 11;\n        a.agreed = 13;\n        a.issuedAt = uint64(block.timestamp);\n        a.expiresAt = uint64(block.timestamp + 1 days);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_KEY, reg.attestationDigest(a));\n        bytes memory sig = abi.encodePacked(r, s, v);\n\n        assertTrue(intake.deliver(id1, a, sig, 200_000), \"first delivery settles p1\");\n        assertTrue(reg.isListed(p1));\n\n        // The identical attestation (same a.requestId, same signature) presented for p2's request.\n        bool deliveredAgain = intake.deliver(id2, a, sig, 200_000);\n        assertFalse(deliveredAgain, \"an already-used oracle attestation must be refused\");\n        assertFalse(reg.isListed(p2), \"p2 listed by an answer that was never about it\");\n    }\n}","reproduction":"State: registry with a mock Intake v2 that pulls the price and plays the writer (same shape as test/mocks/MockIntake.sol). Steps: (1) applicant calls applyListing(p1, \"One\", \"https://example.org/one\", 50, applicant) -> id1, and applyListing(p2, \"Two\", ...) -> id2. (2) Build one attestation {requestId = 1<<128, chainId 1, answerType bool, answer abi.encode(true), panelSize 15, quorum 11, agreed 13, issuedAt now, expiresAt now+1d}, sign it with the registry's oracle signer key for the registry's domain. (3) intake.deliver(id1, a, sig, 200000) -> delivered, isListed(p1) == true. (4) intake.deliver(id2, a, sig, 200000) with the identical attestation and signature. Expected: refused (AlreadyConsumed or equivalent), p2 stays unlisted. Actual: delivered == true and isListed(p2) == true; the same a.requestId settled two different requests. The proof test fails at step 4 on the current code.","severity":"low","snippet":"        _verifyAttestation(a, signature);\n        // An answer signed before this question was asked belongs to another question.\n        if (uint256(a.issuedAt) + ISSUED_AT_TOLERANCE < p.askedAt) {\n            revert AnswerFromBeforeAsk(a.issuedAt);\n        }","title":"A signed oracle answer is never consumed, so the same attestation settles any other open request of the registry"},{"citation":"resolved","description":"Area: Trust Gap seam 3 (access x asymmetry) with an economic edge. `challenge` builds the question from p.rateBps and p.beneficiary as they are at execution time (src/ProjectRegistry.sol:248-250) and the bond on a `yes` is paid to p.beneficiary at settlement time (line 327). `setBeneficiary` (lines 394-401) is open to the current beneficiary at any moment, including in the same block as a pending challenge and while a challenge is open. The challenge definitions re-ask the `beneficiary` rule (the beneficiary must be the owner or a team wallet), so a project whose points were handed to an outsider is challengeable on exactly that ground, yet the outsider can watch the mempool, front-run the challenge with setBeneficiary(project, teamWallet), let the panel judge a question that names the team wallet, collect the 5 IMD bond at the team wallet, and hand the points back to the outsider afterwards. The challenger paid 0.5 IMD plus the bond (5.5 test IMD on Sepolia) to have a state judged that was never put to the panel, and the Challenged event and the Intake's Requested body carry the rewritten beneficiary, so nothing on chain records what the challenger contested. The defender's cost is gas; the defender's gain is the bond, repeatable per challenge. Each side of this is intended in isolation (open setBeneficiary; questions built from current state; bond to the beneficiary), which is why it only appears when the three are read together. Minimal fix preserving the design: let the challenger pin what they contest, e.g. challenge(project, reason, expectedBeneficiary) reverting when p.beneficiary differs (the rate cannot change after listing, so the beneficiary is the only mutable term), and/or snapshot the beneficiary into the open challenge so the bond and the question agree.","line":248,"path":"src/ProjectRegistry.sol","reproduction":"State: project listed at 50 bps with beneficiary = teamWallet; cooldown elapsed. Steps: (1) teamWallet calls setBeneficiary(project, outsider); projectOf(project).beneficiary == outsider. (2) challenger broadcasts challenge(project, \"The beneficiary is not the team: see the outsider wallet.\"). (3) outsider front-runs in the same block with setBeneficiary(project, teamWallet). (4) The challenge executes: the body stored by the Intake (Requested event) contains Strings.toHexString(teamWallet) and does not contain the outsider's address. (5) The panel answers yes to that question; onOracleResult pays 5e18 to teamWallet and the project stays listed. (6) teamWallet calls setBeneficiary(project, outsider) again. Expected: the challenger's fee buys a judgment of the state they named, or the call reverts because the terms changed. Actual: challenger's balance drops by 5.5e18, teamWallet gains 5e18, the beneficiary is the outsider again, and no on-chain record names the outsider in the question. The following Foundry test reproduces steps 1-6 and passes on the current code (it documents the behaviour; it is not a fix-gated proof because the fix changes the challenge ABI):\n\n// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {ProjectRegistry} from \"src/ProjectRegistry.sol\";\nimport {OracleAttestation} from \"src/oracle/OracleAttestation.sol\";\nimport {MockIntake, MintableIMD, MockProject} from \"test/mocks/MockIntake.sol\";\n\n/// The beneficiary can rewrite the terms a challenger pays to contest: `challenge` builds the\n/// question from `p.beneficiary` at execution time, `setBeneficiary` is open to the beneficiary at\n/// any moment, and the challenger cannot pin what they are challenging.\ncontract ChallengeFrontRunTest is Test {\n    uint256 internal constant SIGNER_KEY = 0xA11CE;\n\n    MockIntake internal intake;\n    MintableIMD internal imd;\n    ProjectRegistry internal reg;\n    address internal project;\n    address internal applicant = makeAddr(\"applicant\");\n    address internal challenger = makeAddr(\"challenger\");\n    address internal teamWallet = makeAddr(\"team\");\n    address internal outsider = makeAddr(\"outsider\");\n\n    function setUp() public {\n        vm.roll(1_000);\n        vm.warp(1_700_000_000);\n        intake = new MockIntake();\n        imd = new MintableIMD();\n        reg = new ProjectRegistry(\n            address(intake), address(imd), address(0x57AC), vm.addr(SIGNER_KEY), 1, 5e18, 1 hours\n        );\n        project = address(new MockProject());\n        imd.mint(applicant, 100e18);\n        imd.mint(challenger, 100e18);\n        vm.prank(applicant);\n        imd.approve(address(reg), type(uint256).max);\n        vm.prank(challenger);\n        imd.approve(address(reg), type(uint256).max);\n    }\n\n    function _answer(bytes32 id, bool yes) internal returns (bool) {\n        OracleAttestation.Attestation memory a;\n        a.requestId = bytes32(uint256(uint160(address(this))) << 64 | uint256(id) >> 200);\n        a.chainId = 1;\n        a.answerType = OracleAttestation.ANSWER_BOOL;\n        a.answer = abi.encode(yes);\n        a.panelSize = 15;\n        a.quorum = 11;\n        a.agreed = 13;\n        a.issuedAt = uint64(block.timestamp);\n        a.expiresAt = uint64(block.timestamp + 1 days);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_KEY, reg.attestationDigest(a));\n        return intake.deliver(id, a, abi.encodePacked(r, s, v), 200_000);\n    }\n\n    function _contains(string memory hay, string memory needle) internal pure returns (bool) {\n        bytes memory h = bytes(hay);\n        bytes memory n = bytes(needle);\n        if (n.length > h.length) return false;\n        for (uint256 i; i + n.length <= h.length; ++i) {\n            bool ok = true;\n            for (uint256 j; j < n.length; ++j) {\n                if (h[i + j] != n[j]) {\n                    ok = false;\n                    break;\n                }\n         ","severity":"low","snippet":"        intakeId = _ask(\n            project, p, _challengeBody(project, reason, p.rateBps, p.beneficiary), challengeBond\n        );","title":"A challenger cannot pin the terms they challenge: the beneficiary can rewrite the question and the bond destination by front-running `challenge` with `setBeneficiary`"},{"citation":"resolved","description":"Area: Access Control (roles outside the launched contracts that govern their effect). Neither launched contract has an owner, but the Stacker deposits into the live TestSIMD 0xf9e2eec3b610ec6781f7438ac5fb4bc049d81cc1 whose owner() is 0x4b91078b2374c956A65F7Af0999CaE0a935E6821 (read on Sepolia today; paused() is false; asset() is the TestIMD 0x2b69...1e82 the manifest passes, so the Stacker's AssetMismatch check will pass). That owner holds setPaused(true), which makes every Stacker.credit revert (integrators are told to try/catch and pay plain IMD instead), and rescueERC20(token, to, amount), which can move the whole IMD balance of the vault, i.e. all cashback ever stacked through the Stacker. The Stacker's own max approval to the vault cannot be spent by the vault's owner (Solady's deposit pulls from msg.sender only, and the Stacker holds no IMD between calls), so the exposure is the traders' staked IMD, not the projects' pending credits. This is the documented Sepolia-only design (mainnet uses the renounced sIMD) and matches the brief; it is recorded here as the one privileged power that can take value out of the system, with its actor and preconditions, not as a defect. The Intake side has its own trusted roles: its owner (0x047F...54B7) can change priceOf, callbackGas (1,000,000 on Sepolia today) and the writer; the writer (0x3d3C...25CB) chooses the callback arguments and can withhold answers, which the registry mitigates with expire and the failure path. No action required for this launch; the website should state the vault owner's powers next to the Stacker.","line":89,"path":"src/Stacker.sol","reproduction":"State: live Sepolia, Stacker deployed against TestIMD 0x2b69...1e82 and TestSIMD 0xf9e2...1cc1, any trader with shares. (a) Owner 0x4b91...6821 calls TestSIMD.setPaused(true): project.credit(trader, 1e18) now reverts with EnforcedPause (test/StackerEdges.t.sol exercises this against the local copy of the vault). (b) Owner calls TestSIMD.rescueERC20(0x2b69...1e82, owner, TestIMD.balanceOf(vault)): the vault's IMD balance goes to the owner and every holder's convertToAssets(shares) falls to ~0. Expected under the brief: accepted for the Sepolia rehearsal (owner can pause to test fallbacks). Actual: as expected; no code change in the launched contracts can remove this power.","severity":"info","snippet":"        shares = SIMD.deposit(imdAmount, trader);","title":"Trust assumption: the Sepolia TestSIMD owner can pause the vault (every credit reverts) and sweep all staked IMD, including every trader's cashback"}],"hash":"2b34a4ba044caafd4b7de0fdd040cffc45ec02d8b5e01b7dededdc2405bce0d7","nodeId":"0ba71cf5-f062-435d-a6c9-eef5d7012e21","outcome":"completed","summary":"The review is complete. The findings file is written and valid, the working tree is clean apart from the excluded `.imd-findings.json`, and the scratch directory is removed.\n\n**Outcome.** The permission model of both contracts holds against the Access Control, Trust Gap and Asymmetry guides. I found no critical, high or medium defect. Three findings are recorded, two low and one informational.\n\n- **Low, `onOracleResult`:** a signed oracle attestation is never consumed. The registry keys replay on the Intake's request id only, so the identical signed answer settles any other open request of the registry asked within five minutes. Only the Intake's writer can present it, so this is defence in depth, not an outsider bypass. The proof test fails on the current code and passes once `_consume(a.requestId)` is added after verification.\n- **Low, `challenge` and `setBeneficiary`:** a challenger cannot pin the terms they contest. The question is built from the current beneficiary at execution, and the bond goes to the beneficiary at settlement. A beneficiary who handed points to an outsider can front-run a challenge about that, restore the team wallet, collect the bond on a yes, and hand the points back. A reproduction test documents the full sequence.\n- **Info, `Stacker.credit`:** the live Sepolia vault's owner can pause the vault and sweep every trader's staked IMD. This is the documented Sepolia-only design, recorded as the one privileged power that can take value out.\n\n**Verified against live Sepolia state.** The Intake's price, `requests` getter shape, callback gas, writer and owner were read on chain, and its Sourcify source confirms it marks a request completed before the callback, so `expire` behaves as the code assumes. The vault's `asset()` matches the manifest's TestIMD, and the oracle test token is a plain OpenZeppelin ERC20 with open mint.\n\n**Coverage.** All seven entry points have rows: five hold, two carry findings. Two extra rows record the bond conservation invariant and the launch manifest check, both holding. The full test suite passed before review began.","treeHash":null,"usage":{"cachedInputTokens":1935563,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":49262,"runtime":"claude","turns":38,"wallClockMs":851682}},{"artifacts":[],"attempt":1,"bundleHash":"e88b9103e8880f3758ad47e32d573254e64ef4246e3c3f57dbcdc44311a58e4a","device":"a74f2bc0ce11ed16","findings":[],"hash":"2cd1cdaa416f88eb87a8d3cc63ce099b9bf7a2257ffaba98ac2765014a0b7a22","nodeId":"ec753fa9-93ee-44fb-b33d-46a75db40b43","outcome":"completed","summary":"Added failure-path, fuzz, and accounting invariant tests under `test/`, covering signature validation, replay, deadlines, bond payouts, reentrancy, and rollback.\n\nValidation passed:\n- `forge build`\n- `forge test`: **131 passed, 0 failed**, 7 existing RPC-dependent skips.\n\nOnly `test/` changed. No confirmed implementation defects found.","treeHash":"cbc12c2cb1e440131a0c250fff68cb7c09ef6691","usage":{"cachedInputTokens":2116224,"inputTokens":131797,"model":"gpt-6-astra","outputTokens":25166,"runtime":"codex","turns":7,"wallClockMs":773141}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"37eed9f56188ea8b","findings":[{"citation":"resolved","description":"Boundary (constructor argument edge). The constructor stores `challengeCooldown = challengeCooldown_;` (src/ProjectRegistry.sol:179) without any bound. The only place it is used is the signed-yes branch of `onOracleResult`, where `uint64(block.timestamp) + challengeCooldown` is a checked uint64 addition. For any cooldown >= 2^64 - block.timestamp (about 1.8e19 seconds; block.timestamp is ~1.76e9 today) the addition panics with 0x11. The Intake calls the callback inside a try, so the revert is swallowed: the request is marked completed, the answer is never delivered, and the applicant's 0.5 IMD fee is spent for nothing on every attempt. Rejections, challenges and failures still work, so the registry looks healthy but can never produce a listing, and with no owner it cannot be repaired. The manifest in launch.json passes 3600, which is safe; the defect is that the contract accepts an input that permanently breaks its one purpose instead of refusing it in the constructor (for example `if (challengeCooldown_ > 365 days) revert`), where an empty-chain rehearsal would catch it. Reported at low severity because it needs a wrong deployment input.","line":319,"path":"src/ProjectRegistry.sol","reproduction":"Scratch test test/scratch/CooldownOverflow.t.sol (passes on this code, i.e. reproduces): deploy `new ProjectRegistry(intake, imd, 0x57AC, signer, 1, 5e18, type(uint64).max)` at block.timestamp 1_700_000_000; applicant approves and calls `applyListing(project, \"P\", \"https://example.org/p\", 50, applicant)` -> 0.5 IMD pulled, request opened. Deliver a signed yes (panelSize 15, quorum 11, agreed 13, chainId 1, issuedAt now, expiresAt now+1 day) from the intake address: `onOracleResult` reverts with Panic(0x11) at line 319. Through the mock Intake's `deliver` with 1,000,000 gas the call returns delivered=false, `isListed(project)` stays false, `expire(project)` then clears the slot, and the applicant's balance is still 9.5e18: expected a listing, actual a permanently unlistable registry that keeps charging the fee. With cooldown 3600 the same sequence lists the project.","severity":"low","snippet":"                p.challengeOpenAt = uint64(block.timestamp) + challengeCooldown;","title":"Unbounded challengeCooldown constructor input overflows the uint64 add in the listing callback, so a registry deployed with a large cooldown takes fees but can never list"},{"citation":"resolved","description":"Not a substantiated defect; recorded so the judge can route it. The body (lines 521-533) is strict JSON that the paid door refuses whole on an unknown key (status 1, fee spent, `onOracleFailure` clears the slot). Every key except `consumer` is in the supplied oracle-consumer reference's body schema (v, question, chainId, window, answerType, evidence, panelSize, quorum, validForSeconds, allowAmbiguous, definitions). The reference only says a body may 'name its own consumer' without giving its field names, so `{\"chainId\":..., \"verifyingContract\":...}` cannot be checked offline; the Intake contract itself does not parse the body, so the Sepolia fork test's acceptance proves nothing about the door. The key is also redundant here, because the callback target is this contract and the plane defaults the domain to it. Every text limit was computed and holds: question 1016 bytes (apply) / 1051 bytes (challenge) at maximum inputs against the 2000 limit; definitions 444/228/349/194/163 bytes against 512; keys <= 11 against 64; panel 15/11 within the cap of 100; validForSeconds 86400 within 60..30 days.","line":528,"path":"src/ProjectRegistry.sol","reproduction":"No on-chain reproduction exists: the failure, if any, happens in the off-chain door. Evidence needed: one live `oracle.request` from this body answered with status 0, or the door's `POST /requests/check` accepting the exact body `reg.applyQuestion(...)` produces. Removing the `consumer` object (so the plane uses the callback target) would make the body depend only on documented keys.","severity":"info","snippet":"            '},\"consumer\":{\"chainId\":',","title":"Open verification item: the request body's `consumer` object shape is not in the supplied oracle reference, and a refused body spends the fee on every ask"}],"hash":"413b11ad31703dc8665c567319603511d7173b9173c932ab4fed281171430ef9","nodeId":"6d126e7e-510a-475b-9ab8-13251e2063f8","outcome":"completed","summary":"Review complete. The findings file is written and validated against the tree.\n\n**Outcome:** the math, boundary and numerical-gap passes found no fund-moving defect in either contract. One low-severity boundary defect and one open verification item are recorded in `.imd-findings.json`, with a coverage row for all seven entry points plus two invariants.\n\n**Finding 1, low.** The registry constructor accepts any cooldown, and the only use of it is a checked uint64 addition in the listing callback. A cooldown at the top of the range makes every signed \"yes\" revert inside the Intake's try, so the registry keeps charging the oracle fee but can never list anything, with no owner to repair it. The manifest passes 3600 seconds, which is safe. A scratch test under test/scratch reproduces the panic and the lost fee.\n\n**Finding 2, info.** The request body includes a `consumer` object whose field names are not in the supplied oracle reference, and the door refuses a body whole on an unknown key, spending the fee. This cannot be verified offline, so it is logged as an open item rather than a defect. Every documented limit was computed and holds, including the question length, the five definition lengths, the panel size and the validity window.\n\n**What holds.** Expiry and settlement deadlines are exact complements with no gap. Cold callback gas is at most 75k of the 200k stipend on all paths. Live Sepolia reads confirm the vault's asset is the TestIMD, the vault is unpaused at exactly 1e6 shares per wei, the Intake's price is 0.5 IMD, and its `requests` getter returns the four words the registry decodes. The full suite passes with 94 tests.\n\n**Not reached in depth:** the website's points accounting beyond its listing-period boundary check, and the two reused live dependencies' own internals, which are outside the launch.","treeHash":null,"usage":{"cachedInputTokens":1590339,"inputTokens":386,"model":"claude-fable-5-1","outputTokens":35455,"runtime":"claude","turns":40,"wallClockMs":583625}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"1731fbfe0c4574fb","findings":[{"citation":"resolved","description":"Merged from audit_flow (setBeneficiary allowed while a challenge is open) and audit_permissions (front-running challenge with setBeneficiary); one root cause. challenge() builds the panel's question from p.rateBps and p.beneficiary as they are when the call executes (src/ProjectRegistry.sol:248-250), and a defended challenge pays the bond to p.beneficiary as it is at settlement (line 327: `if (challengeBond != 0) oracleAsset.safeTransfer(p.beneficiary, challengeBond);`). setBeneficiary only checks `listed` and the caller; it does not check `p.ask == Ask.None`, and nothing lets a challenger pin the beneficiary they contest. Every other write to a project record on an open question is blocked with AskOpen; this is the one left open. Two consequences: (a) mid-challenge, the beneficiary named in the question hands the record to another wallet and the bond is paid to a wallet the panel never judged, with the record keeping an unjudged beneficiary and the challenge consumed; (b) a beneficiary that is an outsider (the exact ground the 'beneficiary' definition lets a challenger contest) watches the mempool, front-runs the challenge with setBeneficiary(project, teamWallet), lets the panel judge a question naming the team wallet, collects the 5 IMD bond there, then hands the points back. The challenger pays fee plus bond (5.5 IMD) to have a state judged that was never put to the panel; the Challenged event and the Intake body carry the rewritten beneficiary, so nothing on chain records what was contested. The defender's gain is the bond, repeatable per challenge. Rated medium: a broken guarantee (a challenge judges the state the challenger paid to contest) with a bounded, repeatable transfer from honest challengers to the defender; the bond is test IMD on Sepolia. Minimal fixes that keep the design: revert setBeneficiary while p.ask != Ask.None, snapshot the beneficiary into the open challenge and pay that one, and/or let challenge take an expectedBeneficiary that must equal p.beneficiary.","line":396,"path":"src/ProjectRegistry.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ProjectRegistry} from \"src/ProjectRegistry.sol\";\nimport {OracleAttestation} from \"src/oracle/OracleAttestation.sol\";\nimport {MockIntake, MintableIMD, MockProject} from \"test/mocks/MockIntake.sol\";\n\n/// @dev Fails on the current code: the beneficiary can be swapped while a challenge is open, so the\n/// bond of the defended challenge is paid to a wallet the panel never judged. Passes once the\n/// registry either refuses `setBeneficiary` while a question is open or pays the beneficiary that\n/// the challenge question named.\ncontract BeneficiaryMidChallengeTest is Test {\n    uint256 internal constant SIGNER_KEY = 0xA11CE;\n    uint256 internal constant BOND = 5e18;\n\n    MockIntake internal intake;\n    MintableIMD internal imd;\n    ProjectRegistry internal reg;\n    address internal project;\n    address internal judged = makeAddr(\"judgedBeneficiary\");\n    address internal swapped = makeAddr(\"swappedBeneficiary\");\n    address internal applicant = makeAddr(\"applicant\");\n    address internal challenger = makeAddr(\"challenger\");\n\n    function setUp() public {\n        vm.roll(1_000);\n        vm.warp(1_700_000_000);\n        intake = new MockIntake();\n        imd = new MintableIMD();\n        reg = new ProjectRegistry(address(intake), address(imd), address(0x57AC), vm.addr(SIGNER_KEY), 1, BOND, 1 hours);\n        project = address(new MockProject());\n        imd.mint(applicant, 100e18);\n        imd.mint(challenger, 100e18);\n        vm.prank(applicant);\n        imd.approve(address(reg), type(uint256).max);\n        vm.prank(challenger);\n        imd.approve(address(reg), type(uint256).max);\n    }\n\n    function _answer(bytes32 id, bool yes) internal returns (bool) {\n        OracleAttestation.Attestation memory a;\n        a.requestId = keccak256(abi.encode(\"uuid\", id));\n        a.chainId = 1;\n        a.answerType = OracleAttestation.ANSWER_BOOL;\n        a.answer = abi.encode(yes);\n        a.panelSize = 15;\n        a.quorum = 11;\n        a.agreed = 13;\n        a.issuedAt = uint64(block.timestamp);\n        a.expiresAt = uint64(block.timestamp + 1 days);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_KEY, reg.attestationDigest(a));\n        return intake.deliver(id, a, abi.encodePacked(r, s, v), 200_000);\n    }\n\n    function test_defendedBondGoesToTheBeneficiaryThePanelJudged() public {\n        vm.prank(applicant);\n        bytes32 id = reg.applyListing(project, \"PLEA\", \"https://github.com/khaed1/plea\", 50, judged);\n        assertTrue(_answer(id, true));\n        assertTrue(reg.isListed(project));\n\n        vm.warp(block.timestamp + 1 hours);\n        vm.prank(challenger);\n        id = reg.challenge(project, \"It credits the owner's wallet outside trades.\");\n\n        // While the question (which names `judged`) is open, the beneficiary hands the record over.\n        vm.prank(judged);\n        (bool ok,) = address(reg).call(abi.encodeCall(reg.setBeneficiary, (project, swapped)));\n        ok; // the fix may refuse this call or let it through and snapshot; either is accepted here\n\n        assertTrue(_answer(id, true), \"defended\");\n        assertTrue(reg.isListed(project));\n        assertEq(imd.balanceOf(judged), BOND, \"bond must reach the beneficiary the panel judged\");\n        assertEq(imd.balanceOf(swapped), 0, \"an unjudged wallet must not take the bond\");\n    }\n}","reproduction":"Mock Intake v2 (test/mocks/MockIntake.sol), bond 5e18, cooldown 1h. (1) applicant: applyListing(project, \"PLEA\", \"https://github.com/khaed1/plea\", 50, B1); writer delivers a signed yes -> listed, beneficiary B1. (2) warp +1h; challenger: challenge(project, reason) -> question text names B1; registry holds the 5e18 bond. (3) B1: setBeneficiary(project, B2) -> succeeds (no AskOpen check). (4) writer delivers a signed yes for the challenge. Actual: Defended, imd.balanceOf(B2) == 5e18, imd.balanceOf(B1) == 0, projectOf(project).beneficiary == B2. Expected: step 3 reverts while a question is open, or the bond goes to B1, the beneficiary the panel judged. Front-run variant: with beneficiary == outsider, outsider sends setBeneficiary(project, teamWallet) in the same block ahead of challenge(project, \"beneficiary is the outsider ...\"); the stored body contains Strings.toHexString(teamWallet) and not the outsider; a yes pays 5e18 to teamWallet; setBeneficiary(project, outsider) restores the state; challenger is down 5.5e18. Proof test (fails on this code with 'bond must reach the beneficiary the panel judged: 0 != 5000000000000000000'): test/scratch/Proof_3a8ca86457d4.t.sol.","severity":"medium","snippet":"        if (!p.listed) revert NotListed();\n        if (msg.sender != p.beneficiary) revert NotBeneficiary();\n        if (beneficiary == address(0)) revert ZeroAddress();\n        p.beneficiary = beneficiary;","title":"The beneficiary can rewrite the terms a challenge is judged on and the bond destination, before or during the challenge"},{"citation":"resolved","description":"From audit_permissions; reproduced. onOracleResult binds an answer to a request only through the Intake's id (projectOfIntake[intakeId]) and the signature check. It never calls the inherited _consume(a.requestId) (the `consumed` mapping is unused) and never compares a.questionHash with anything, so one valid attestation, obtained for one question, is also a fully verified answer for every other open question of this registry asked within ISSUED_AT_TOLERANCE (5 minutes) of its issuedAt and before its expiresAt: a yes to project A's application lists project B; a yes to a challenge of A defends B and pays B's beneficiary the bond. Only the Intake can reach the callback and the Intake's writer picks the arguments, so this is defence in depth against a writer bug or a replayed delivery, not a bypass for an outsider; the oracle-consumer reference asks consumers to consume one of the two ids once, and the registry consumes only the intake id. Fix: call _consume(a.requestId) after _verifyAttestation (about 22k gas, within the 200k stipend measured by test/RegistryCallbackGas.t.sol).","line":297,"path":"src/ProjectRegistry.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ProjectRegistry, IIntake} from \"src/ProjectRegistry.sol\";\nimport {OracleAttestation} from \"src/oracle/OracleAttestation.sol\";\n\ncontract ReuseIMD is ERC20 {\n    constructor() ERC20(\"Identity.md (test)\", \"IMD\") {}\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\ncontract ReuseProject {}\n\n/// A minimal Intake v2 stand-in: pulls the price, records the callback, and lets the test play the\n/// writer, calling the recorded callback from the intake's own address under a gas stipend.\ncontract ReuseIntake is IIntake {\n    bytes32 public constant ACTION = \"oracle.request@oracle-1\";\n    uint256 public constant PRICE = 0.5e18;\n\n    struct Req {\n        address payer;\n        address target;\n        bytes4 selector;\n        bool completed;\n    }\n\n    mapping(bytes32 => Req) internal _reqs;\n    uint256 public count;\n\n    function priceOf(bytes32 action, address) external pure returns (uint256) {\n        return action == ACTION ? PRICE : 0;\n    }\n\n    function requestWithFailure(\n        bytes32 action,\n        bytes calldata,\n        Callback calldata callback,\n        bytes4,\n        address asset,\n        uint256 amount\n    ) external returns (bytes32 id) {\n        require(action == ACTION && amount >= PRICE, \"not sold\");\n        IERC20(asset).transferFrom(msg.sender, address(0x7EA5), amount);\n        id = keccak256(abi.encode(address(this), ++count));\n        _reqs[id] = Req(msg.sender, callback.target, callback.selector, false);\n    }\n\n    function requests(bytes32 id) external view returns (address, address, bytes4, bool) {\n        Req storage r = _reqs[id];\n        return (r.payer, r.target, r.selector, r.completed);\n    }\n\n    function deliver(\n        bytes32 id,\n        OracleAttestation.Attestation calldata a,\n        bytes calldata sig,\n        uint256 gasLimit\n    ) external returns (bool delivered) {\n        Req storage r = _reqs[id];\n        r.completed = true;\n        (delivered,) = r.target.call{gas: gasLimit}(abi.encodeWithSelector(r.selector, id, a, sig));\n    }\n}\n\n/// One signed attestation settles two different open requests: the registry keys replay on the\n/// Intake's id only and never consumes the oracle's `a.requestId`, so a signed answer obtained for\n/// one question is accepted again for any other open question of this registry (asked within\n/// ISSUED_AT_TOLERANCE of its issue) whenever the Intake's writer presents it.\ncontract AttestationReuseTest is Test {\n    uint256 internal constant SIGNER_KEY = 0xA11CE;\n\n    ReuseIntake internal intake;\n    ReuseIMD internal imd;\n    ProjectRegistry internal reg;\n    address internal applicant = makeAddr(\"applicant\");\n\n    function setUp() public {\n        vm.roll(1_000);\n        vm.warp(1_700_000_000);\n        intake = new ReuseIntake();\n        imd = new ReuseIMD();\n        reg = new ProjectRegistry(\n            address(intake), address(imd), address(0x57AC), vm.addr(SIGNER_KEY), 1, 5e18, 1 hours\n        );\n        imd.mint(applicant, 100e18);\n        vm.prank(applicant);\n        imd.approve(address(reg), type(uint256).max);\n    }\n\n    function test_sameSignedAnswerSettlesTwoRequests() public {\n        address p1 = address(new ReuseProject());\n        address p2 = address(new ReuseProject());\n        vm.startPrank(applicant);\n        bytes32 id1 = reg.applyListing(p1, \"One\", \"https://example.org/one\", 50, applicant);\n        bytes32 id2 = reg.applyListing(p2, \"Two\", \"https://example.org/two\", 50, applicant);\n        vm.stopPrank();\n\n        OracleAttestation.Attestation memory a;\n        a.requestId = bytes32(uint256(1) << 128);\n        a.chainId = 1;\n        a.questionHash = keccak256(\"question about p1\");\n        a.answerType = OracleAttestation.ANSWER_BOOL;\n        a.answer = abi.encode(true);\n        a.panelSize = 15;\n        a.quorum = 11;\n        a.agreed = 13;\n        a.issuedAt = uint64(block.timestamp);\n        a.expiresAt = uint64(block.timestamp + 1 days);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_KEY, reg.attestationDigest(a));\n        bytes memory sig = abi.encodePacked(r, s, v);\n\n        assertTrue(intake.deliver(id1, a, sig, 200_000), \"first delivery settles p1\");\n        assertTrue(reg.isListed(p1));\n\n        // The identical attestation (same a.requestId, same signature) presented for p2's request.\n        bool deliveredAgain = intake.deliver(id2, a, sig, 200_000);\n        assertFalse(deliveredAgain, \"an already-used oracle attestation must be refused\");\n        assertFalse(reg.isListed(p2), \"p2 listed by an answer that was never about it\");\n    }\n}","reproduction":"Mock Intake v2 that pulls the price and plays the writer. (1) applicant calls applyListing(p1, \"One\", \"https://example.org/one\", 50, applicant) -> id1, then applyListing(p2, \"Two\", \"https://example.org/two\", 50, applicant) -> id2. (2) Build one attestation {requestId = 1<<128, chainId 1, answerType bool, answer abi.encode(true), panelSize 15, quorum 11, agreed 13, issuedAt now, expiresAt now+1d}, sign it with the registry's oracle signer key over reg.attestationDigest(a). (3) intake.deliver(id1, a, sig, 200000) -> delivered, isListed(p1) == true. (4) intake.deliver(id2, a, sig, 200000) with the identical attestation and signature. Expected: refused (AlreadyConsumed), p2 stays unlisted. Actual: delivered == true and isListed(p2) == true. Proof test fails at step 4 on this code: test/scratch/Proof_28973d00bb2d.t.sol ('an already-used oracle attestation must be refused').","severity":"low","snippet":"        _verifyAttestation(a, signature);","title":"A signed oracle answer is never consumed and its questionHash never checked, so one attestation can settle every open request of the registry"},{"citation":"resolved","description":"Merged from audit_economics (low) and audit_flow (info); one root cause. credit is permissionless, takes any non-zero amount and any trader, and deposits with the trader as share recipient. TestSIMD._beforeTokenTransfer sets lastDepositBlock[to] = block.number on every positive mint, and _withdraw reverts SameBlockRedeem while block.number == lastDepositBlock[owner] (maxRedeem/maxWithdraw read 0). With the vault's decimals offset of 6, previewDeposit(1) is 1e6 shares, so a 1-wei credit always passes the ZeroShares check. A griefer who front-runs a trader's redeem with Stacker.credit(trader, 1) in the same block makes it revert, for 1 wei of freely minted TestIMD plus gas, repeatable every block; each grief also emits a Stacked event the site's leaderboards read. The vault is live and reused, and TestSIMD.deposit(1, victim) does the same directly, so the Stacker only adds a cheap labelled path; no funds are lost, the exit is delayed at the griefer's will. A minimum credit in the Stacker raises the cost only; the complete fix is in the vault (stamp only when receiver == caller), which this launch does not redeploy. Also an integration note for the website: a redeem that reverts right after a credit is this.","line":89,"path":"src/Stacker.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\nimport \"forge-std/Test.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {Stacker, IStakedIMD} from \"src/Stacker.sol\";\nimport {TestIMD} from \"test/mocks/TestIMD.sol\";\nimport {TestSIMD} from \"test/mocks/TestSIMD.sol\";\ncontract HoldGriefTest is Test {\n    function test_dustCreditMustNotBlockTraderRedeem() public {\n        TestIMD imd = new TestIMD();\n        TestSIMD v = new TestSIMD(address(imd), address(this));\n        Stacker s = new Stacker(IERC20(address(imd)), IStakedIMD(address(v)));\n        address project = address(0xBEEF); address trader = address(0xCAFE); address griefer = address(0xBAD);\n        deal(address(imd), project, 100e18); deal(address(imd), griefer, 1);\n        vm.prank(project); imd.approve(address(s), type(uint256).max);\n        vm.prank(griefer); imd.approve(address(s), type(uint256).max);\n        vm.prank(project); uint256 sh = s.credit(trader, 10e18);\n        vm.roll(block.number + 100);\n        vm.prank(griefer); try s.credit(trader, 1) {} catch {}\n        vm.prank(trader);\n        v.redeem(sh, trader, trader); // reverts SameBlockRedeem today\n    }\n}","reproduction":"Local TestIMD + TestSIMD (test/mocks) and the Stacker. (1) project approves and calls credit(trader, 10e18) -> shares sh; roll 100 blocks; maxRedeem(trader) == sh. (2) In the trader's redeem block, griefer holding 1 wei tIMD with an approval calls credit(trader, 1); returns 1e6 shares. (3) maxRedeem(trader) == 0 and trader's redeem(sh, trader, trader) reverts SameBlockRedeem (surfaced as RedeemMoreThanMax by Solady). Expected: a 1-wei third-party credit does not change what the trader can do in that block. Actual: the exit is blocked for that block, repeatable. Proof test fails on this code with RedeemMoreThanMax(): test/scratch/Proof_e0d57eb25bc9.t.sol (it wraps the dust credit in try/catch, so a minimum-credit fix in the Stacker makes it pass). Live Sepolia reads by the specialist: previewDeposit(1) == 1000000, paused() == false.","severity":"low","snippet":"        shares = SIMD.deposit(imdAmount, trader);","title":"Anyone can credit 1 wei to a trader to stamp the TestSIMD one-block hold and block that trader's redeem in the same block"},{"citation":"resolved","description":"From audit_math; reproduced with test/scratch/CooldownOverflow.t.sol. The constructor stores challengeCooldown_ (line 179) with no bound; its only use is the checked uint64 addition in the signed-yes branch of onOracleResult. For any cooldown >= 2^64 - block.timestamp the add panics (0x11). The Intake calls the callback inside a try, so the revert is swallowed: the request is marked completed, no listing happens, and the applicant's 0.5 IMD is spent on every attempt. Rejections, challenges and failures still work, so the registry looks healthy but can never produce a listing, and with no owner it cannot be repaired. launch.json passes 3600, which is safe, so this needs a wrong deployment input; the defect is that the constructor accepts an input that permanently breaks the contract's one purpose instead of refusing it (e.g. revert when challengeCooldown_ > 365 days), where the empty-chain rehearsal would catch it.","line":319,"path":"src/ProjectRegistry.sol","reproduction":"Deploy new ProjectRegistry(intake, imd, 0x57AC, signer, 1, 5e18, type(uint64).max) at block.timestamp 1_700_000_000; applicant approves and calls applyListing(project, \"P\", \"https://example.org/p\", 50, applicant) -> 0.5 IMD pulled. Deliver a signed yes (panelSize 15, quorum 11, agreed 13, chainId 1, issuedAt now, expiresAt now+1 day) through the mock Intake's deliver with 1,000,000 gas. Actual: delivered == false (Panic 0x11 at line 319), isListed(project) == false, applicant balance 9.5e18. With cooldown 3600 the same sequence lists the project. Both cases pass as written in test/scratch/CooldownOverflow.t.sol (test_maxCooldownNeverLists, test_normalCooldownLists).","severity":"low","snippet":"                p.challengeOpenAt = uint64(block.timestamp) + challengeCooldown;","title":"Unbounded challengeCooldown constructor input overflows the uint64 add in the listing callback, so a registry deployed with a large cooldown takes fees but can never list"},{"citation":"resolved","description":"From audit_flow; reproduced by reading every write to rateBps. p.rateBps is written only in applyListing (line 226), which requires !listed; setBeneficiary changes only the beneficiary. challengeQuestion tells the panel 'It is listed at a cashback rate of <p.rateBps> basis points' and the 'rate' definition requires that '<r> must be the rate in force now', while the same definition explicitly allows a rate that can change inside 25-100 bps. So a listed project that moves its rate from 50 to 75 bps, which the rules permit, is bound to fail the rate rule on any challenge, and can only restate its rate by being delisted first (losing the listing period and paying two more oracle fees plus a challenger's bond flow). The contract's own rules and its question text contradict each other for a state the rules allow. Fix options that keep the design: a beneficiary-opened rate-restatement ask that keeps the listing, or a challenge question that only requires the rate to be within 25-100 bps and names the stated rate as informational.","line":249,"path":"src/ProjectRegistry.sol","reproduction":"(1) applyListing(project, name, url, 50, B) answered yes -> projectOf(project).rateBps == 50, listed. (2) The project changes its on-chain cashback rate to 75 bps (allowed by the 'rate' definition). (3) No function updates rateBps while listed: setBeneficiary(project, x) leaves rateBps at 50; applyListing(project, ..., 75, B) reverts AlreadyListed. (4) challenge(project, \"rate is now 75\") sends challengeQuestion(project, reason, 50, B) containing 'It is listed at a cashback rate of 50 basis points' and the definition '... and 50 must be the rate in force now.' A panel following the definitions answers false -> Delisted. Expected: a listed project whose rate is still inside 25-100 bps has a way to restate it without losing its listing.","severity":"low","snippet":"            project, p, _challengeBody(project, reason, p.rateBps, p.beneficiary), challengeBond","title":"A challenge restates the rate recorded at application and there is no path to update it, so a project that lawfully changes its rate is delisted on its next challenge"},{"citation":"resolved","description":"From audit_flow; reproduced. applyListing and challenge are permissionless and a project has one open ask at a time (the same check at line 244). A third party can front-run the team's application with wrong terms (another beneficiary or rate); the panel answers no and the slot reopens only after the answer or after PENDING_EXPIRY (1 day) via expire; the griefer re-applies as the slot opens. The same slot rule applies to challenges: a beneficiary can keep a soft self-challenge open (bond returns to itself on yes, the earlier fix stops the cooldown from restarting) so a pointed honest challenge is refused AskOpen until the slot briefly reopens. On Sepolia the oracle asset is open-mint, so each cycle costs gas only. ADAPTATION.md records the application half as a retained limit of the approved 'anyone applies' design (imported finding 04f9947f...). Recorded for coverage; no mechanism change is proposed within the approved ownerless design.","line":222,"path":"src/ProjectRegistry.sol","reproduction":"(1) griefer: applyListing(project, \"x\", \"https://example.org/x\", 25, griefer) paying 0.5 IMD. (2) team: applyListing(project, name, url, 50, team) -> reverts AskOpen. (3) after the panel's no (Rejected) or expire(project) once 1 day passed, the griefer re-applies in the block the slot opens; the team is again refused AskOpen. Challenge variant: beneficiary calls challenge(project, \"fine\") as soon as challengeOpenAt passes; an honest challenge(project, \"credits owner outside trades\") in the same window reverts AskOpen. Expected per the brief: the team can apply for its own project and anyone can challenge; actual: either can be kept out for as long as the occupier pays 0.5 IMD per cycle.","severity":"info","snippet":"        if (p.ask != Ask.None) revert AskOpen();","title":"One open question per project lets anyone occupy a project's application or challenge slot for 0.5 IMD per cycle (documented design limit)"},{"citation":"resolved","description":"From audit_math; kept as an unverified item because it cannot be reproduced on chain. The body (lines 521-533) is strict JSON that the paid door refuses whole on an unknown key (status 1, fee spent, onOracleFailure clears the slot). Every key except `consumer` is in the oracle-consumer reference's documented body (v, question, chainId, window, answerType, evidence, panelSize, quorum, validForSeconds, allowAmbiguous, definitions). The reference says only that a body may 'name its own consumer' without giving the object's field names, so {\"chainId\":..., \"verifyingContract\":...} cannot be checked offline; the Intake contract does not parse the body, so the Sepolia fork test proves nothing about the door. If the shape is wrong, every application and challenge fails with body_invalid for the life of the registry, each spending 0.5 IMD, and no owner can change the body. The key is also redundant: the callback target is this contract on the same chain and the plane defaults the domain to it. Text limits were checked and hold (question <= 1051 bytes of 2000; each definition <= 444 of 512; panel 15/11; validForSeconds 86400).","line":528,"path":"src/ProjectRegistry.sol","reproduction":"No on-chain reproduction: the failure, if any, is in the off-chain door. Evidence needed before launch: one live oracle.request from the exact body reg.applyQuestion(...) produces answered with status 0, or the door's POST /requests/check accepting that body. Removing the `consumer` object makes the body depend only on documented keys at no loss, since the plane signs for the callback target.","severity":"info","snippet":"            '},\"consumer\":{\"chainId\":',","title":"Open verification item: the request body's `consumer` object is not in the supplied oracle reference's body schema, and a refused body spends the fee on every ask with no way to fix an ownerless regis"},{"citation":"resolved","description":"From audit_permissions; confirmed against test/mocks/TestSIMD.sol (the verbatim copy of the live vault's logic: setPaused, rescueERC20, rescueETH, renounceOwnership guarded while paused). Neither launched contract has an owner, but every credit lands in the live TestSIMD 0xf9e2eec3b610ec6781f7438ac5fb4bc049d81cc1 whose owner (read by the specialist as 0x4b91078b2374c956A65F7Af0999CaE0a935E6821) can setPaused(true), making every Stacker.credit revert (integrators are told to try/catch), and rescueERC20(token, to, amount), which can move the vault's whole IMD balance, i.e. all cashback ever stacked. The Stacker's max approval to the vault cannot be spent by the vault owner (Solady deposit pulls from msg.sender only, and the Stacker holds no IMD between calls), so the exposure is traders' staked IMD, not projects' pending credits. This is the documented Sepolia-only design and matches the brief; recorded as the one privileged power that can take value out of the system, not as a defect. The website should state it beside the Stacker.","line":89,"path":"src/Stacker.sol","reproduction":"Live Sepolia, Stacker deployed per launch.json, any trader with shares. (a) owner: TestSIMD.setPaused(true) -> project.credit(trader, 1e18) reverts EnforcedPause (test/StackerEdges.t.sol exercises this on the local copy). (b) owner: TestSIMD.rescueERC20(0x2b69099e59b05901faa1dd164fabf098bf831e82, owner, TestIMD.balanceOf(vault)) -> the vault's IMD goes to the owner and every holder's convertToAssets(shares) falls to ~0. Expected under the brief: accepted for the Sepolia rehearsal. No change in the launched contracts can remove this power.","severity":"info","snippet":"        shares = SIMD.deposit(imdAmount, trader);","title":"Trust assumption: the Sepolia TestSIMD owner can pause the vault (every credit reverts) and sweep all staked IMD, including every trader's cashback"}],"hash":"49d15629000f963e0b7c215c01ed2a49792a5ff46d54a6d98e5e35fa059bdd4b","nodeId":"984aab83-0c2b-402a-a829-77a31b962f7d","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds the result. Nothing in the tree outside that file and `test/scratch/` was touched.\n\n**What I found.** The ten specialist findings reduce to eight after merging, and every one reproduced. The three attached proofs all fail on the current code for the reasons their findings state. The project's own suite is green at 131 tests.\n\n**Findings kept, by severity:**\n\n1. **Medium.** The beneficiary can change the terms a challenge is judged on and where the bond goes, both by front-running `challenge` and mid-challenge, because `setBeneficiary` has no open-ask check and the challenger cannot pin the beneficiary. Merged from the flow and permissions areas and raised from low, since an honest challenger loses fee plus bond to a defender who evaded the question. Proof attached.\n2. **Low.** A signed attestation is never consumed and its question hash never checked, so one answer can settle every open request within the issuance tolerance. Writer-only reach, so defence in depth. Proof attached.\n3. **Low.** A 1-wei credit stamps any trader's one-block vault hold and blocks their redeem in that block. Merged from the economics and flow areas. Proof attached.\n4. **Low.** An unbounded cooldown constructor input overflows the uint64 add in the listing callback, so a mis-deployed registry takes fees and can never list. I confirmed this with my own scratch test; the manifest's value of 3600 is safe.\n5. **Low.** A listed project cannot restate its rate, yet the challenge question demands the rate recorded at application be the one in force.\n6. **Info.** One open question per project lets anyone occupy the application or challenge slot per 0.5 IMD cycle. Documented design limit; I added the self-challenge variant.\n7. **Info.** The body's `consumer` object is not in the supplied reference schema. Unverifiable offline, but if refused it would permanently break an ownerless registry, so I stated the evidence needed before launch.\n8. **Info.** Trust assumption that the live TestSIMD owner can pause the vault and sweep all staked IMD.\n\n**Coverage.** All seven entry points are answered, plus three invariant rows for bond conservation, the manifest and factory model, and attestation verification. The manifest itself passes every schema and ordering check.\n\n**Dropped or downgraded.** Nothing was dropped. The slither unused-return line on `expire` is a false positive, and the aderyn reentrancy line on `credit` is guarded by `nonReentrant` with only totals written after the call.","treeHash":null,"usage":{"cachedInputTokens":943960,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":29314,"runtime":"claude","turns":27,"wallClockMs":418690}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"589ef002581a5371","findings":[{"citation":"resolved","description":"Settles earlier finding 739a4a9f (low). It still reproduces unchanged: credit is permissionless, any non-zero amount mints shares to `trader` (decimals offset 6, so previewDeposit(1) = 1e6 shares), and the live vault's _beforeTokenTransfer stamps lastDepositBlock[to] on every mint while _withdraw reverts SameBlockRedeem in that block. The author's dispute holds on the facts: the root cause is in the reused TestSIMD (test/mocks/TestSIMD.sol lines 109 and 122, the verbatim copy of the live vault), TestSIMD.deposit(1, victim) does the same without the Stacker, this launch does not redeploy the vault, and a Stacker minimum would reject legitimate small cashback (0.25% of a small trade) without closing the direct path. No funds are at risk; the exit is deferred one block per griefing transaction. The website and README now explain the delay beside staking (VaultTrustRegression covers both paths). Downgraded to info as a documented limitation of a reused dependency; no change to the launched contracts is requested.","line":89,"path":"src/Stacker.sol","reproduction":"Proof .imd/reads/proofs/Proof_e0d57eb25bc9.t.sol copied to test/scratch and run against this code: still fails with RedeemMoreThanMax(). Steps: (1) project credits trader 10e18, roll 100 blocks, maxRedeem(trader) == shares. (2) In the trader's redeem block a griefer holding 1 wei TestIMD with an approval calls Stacker.credit(trader, 1) -> returns 1e6 shares. (3) maxRedeem(trader) == 0; trader's redeem(shares, trader, trader) reverts SameBlockRedeem (surfaced as RedeemMoreThanMax). Next block the redeem succeeds. Expected per the vault's intent: a third party cannot stamp a hold for free; actual: it can, for 1 wei plus gas per block, through the vault directly or through the Stacker.","severity":"info","snippet":"        shares = SIMD.deposit(imdAmount, trader);","title":"Retained dependency limit (disputed, agreed): a 1-wei third-party credit stamps the reused TestSIMD one-block hold and defers the trader's redeem by a block"},{"citation":"resolved","description":"Settles earlier finding 3b34e045 (info). Unchanged and still reproducible: applyListing and _challenge (line 274) are permissionless and refuse a second ask while one is open, so a third party can hold the slot with a wrong-terms application or a soft self-challenge until the panel answers or PENDING_EXPIRY (1 day) passes, then re-occupy it in the same block. The 'anyone applies, anyone challenges' ownerless design the brief requests has no authenticated applicant, so this is a property of the approved design rather than a defect in its implementation; ADAPTATION.md and the site README disclose both halves, and test_selfChallengeOccupiesSlotOnlyUntilItSettles shows the slot reopening after settlement. Recorded for coverage; no mechanism change is requested.","line":232,"path":"src/ProjectRegistry.sol","reproduction":"(1) griefer: applyListing(project, \"x\", \"https://example.org/x\", 25, griefer) paying 0.5 IMD. (2) team: applyListing(project, name, url, 50, team) -> reverts AskOpen. (3) after the panel's no or expire(project) one day later, the griefer re-applies in the block the slot opens; the team is again refused AskOpen. Challenge variant: as soon as challengeOpenAt passes the beneficiary calls challengeForBeneficiary(project, \"fine\", self); an honest challenge in the same window reverts AskOpen until that question settles.","severity":"info","snippet":"        if (p.ask != Ask.None) revert AskOpen();","title":"Retained design limit (disputed, agreed): one open question per project lets anyone occupy a project's application or challenge slot for 0.5 IMD per cycle"},{"citation":"resolved","description":"Settles earlier finding db2c500c (info). Neither launched contract has an owner, but every credit lands in the live TestSIMD 0xf9e2eec3b610ec6781f7438ac5fb4bc049d81cc1 whose owner holds setPaused and rescueERC20 (test/mocks/TestSIMD.sol is the verbatim copy). The Stacker's max approval to the vault is not exposed to that owner (Solady deposit pulls from msg.sender only and the Stacker holds nothing between calls), so the exposure is traders' staked IMD. The brief requires reusing this vault, so no change in the launched code can remove the power; the website now states the pause and sweep powers beside the Stacker and VaultTrustRegression exercises the sweep. Recorded as the one privileged power outside the launched contracts that can take value out of the system.","line":89,"path":"src/Stacker.sol","reproduction":"Local copy of the vault (test/mocks/TestSIMD.sol) or live Sepolia. (a) owner: TestSIMD.setPaused(true); project.credit(trader, 1e18) reverts EnforcedPause (test/StackerEdges.t.sol). (b) owner: TestSIMD.rescueERC20(TestIMD, owner, TestIMD.balanceOf(vault)); the vault's IMD goes to the owner and every holder's convertToAssets(shares) falls to ~0 (test/VaultTrustRegression.t.sol). Expected under the brief: accepted for the Sepolia rehearsal.","severity":"info","snippet":"        shares = SIMD.deposit(imdAmount, trader);","title":"Trust assumption (disputed, agreed): the reused Sepolia TestSIMD owner can pause the vault, making every credit revert, and sweep all staked IMD including every trader's cashback"}],"hash":"54cf370ab21deab26a1b6e6415576eef5f08c13cca871bd63b0c5bbded7c47e2","nodeId":"984aab83-0c2b-402a-a829-77a31b962f7d","outcome":"completed","summary":"The review is complete and the findings file is written. Nothing further depends on another result.\n\n**Outcome: all four fixes hold and nothing new reproduces.** The revised `src/ProjectRegistry.sol` closes every defect I raised last round, and the three retained items are documented limits of the approved design or of reused dependencies, not defects in the launched code. The file `.imd-findings.json` holds three info-level entries and a 14-row coverage record. The working tree is otherwise unchanged.\n\n**Settled findings, each confirmed against the code and the attached proofs:**\n\n- **Beneficiary rewrite around a challenge (medium).** Fixed. `setBeneficiary` now reverts while a question is open, and a real handoff permanently forces the pinned `challengeForBeneficiary` path, so a front-run that changes the wallet also disables the legacy call before any fee is pulled. Both earlier proofs pass on this code and the author's regression tests cover the same-block front-run on each path.\n- **Attestation never consumed (low).** Fixed. The callback consumes the oracle request id after verification and before effects. The earlier proof passes, and cold listing and defended callbacks still complete under the 200k stipend.\n- **Unbounded challenge cooldown (low).** Fixed. The constructor refuses a cooldown above 365 days without any external call. The manifest keeps 3600.\n- **Challenge restated the application rate (low).** Fixed. The challenge definition now judges the current rate within 25 to 100 basis points and labels the stated rate as historical.\n- **Unverified `consumer` body key (info).** Dropped. The oracle docs at imd.fun define the key with exactly the two fields the registry sends.\n\n**Retained at info, agreeing with the author's disputes:**\n\n- The 1-wei credit hold stamp still reproduces, but the root cause is the reused vault's own transfer hook, which a Stacker minimum would not close. The site now explains the one-block delay.\n- Slot occupation by any payer is a property of the ownerless anyone-applies design.\n- The TestSIMD owner's pause and sweep powers are the one external privilege, now disclosed on the site.\n\nThe full suite of 150 tests passes. The manifest validates: schema keys only, argument counts match both constructors in order, and the notes are within the limit. Static-analysis leads were checked and are false positives or guarded.","treeHash":null,"usage":{"cachedInputTokens":674113,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":14300,"runtime":"claude","turns":17,"wallClockMs":306690}},{"artifacts":[],"attempt":1,"bundleHash":"50a593e4348c973ad333417f1b8d8bf6ecf7d3f46ddddf6911c848c8fc09d73c","device":"629adec6a25d9241","findings":[],"hash":"6d4b0dea6a73e171dcdc57647c2e52c97bcde0c11a7e8748388dcbb74e77ca5d","nodeId":"6a1f1ef6-55bf-477c-8dd0-2fc8a23a09c0","outcome":"completed","summary":"Implemented launch adaptations, audit fixes, regression tests, and the static Sepolia site.\n\nChecks passed: 94 Foundry tests, 4 Sepolia fork tests, 18 website tests, and the supplied protected factory check.\n\nChanges and remaining limitations are documented in [ADAPTATION.md](/Users/zhuminquan/.identitymd-3/work/0b69e5bd-873f-4bcf-9e02-ef1a00a4b2f5/6a1f1ef6-55bf-477c-8dd0-2fc8a23a09c0/ADAPTATION.md).\n\nDeployment and publication remain platform steps. The site awaits confirmed addresses. Chrome could not start here, so visual browser verification remains pending.","treeHash":"6d6cba5a717906e0c49fc1a8d17820480bc90983","usage":{"cachedInputTokens":6394496,"inputTokens":173227,"model":"gpt-6-astra","outputTokens":56110,"runtime":"codex","turns":9,"wallClockMs":1664663}},{"artifacts":[],"attempt":1,"bundleHash":"aa4ce799df0dfbdca54383f33bec542c77cb527d2b2ee7b09a2ff4e62bb07195","device":"d2bae9a4a05e8265","findings":[],"hash":"79abb0ffd0ffd59cb021977e1fcab4eb2bd863ae6f1b6b5b8f97a0c8972afc40","nodeId":"6a1f1ef6-55bf-477c-8dd0-2fc8a23a09c0","outcome":"completed","summary":"Completed the revision: fixed beneficiary/bond races, attestation replay, cooldown validation, and rate-change challenges. Updated the website and documented retained vault risks.\n\n- `forge build` passed.\n- 112 project tests passed; 7 optional fork tests skipped.\n- Supplied reviewer proof passed unchanged.\n- 22 website tests passed.\n\nAll 13 findings are answered in [.imd-responses.json](/home/imd/.identitymd/work/0b69e5bd-873f-4bcf-9e02-ef1a00a4b2f5/6a1f1ef6-55bf-477c-8dd0-2fc8a23a09c0/.imd-responses.json), with changes documented in [ADAPTATION.md](/home/imd/.identitymd/work/0b69e5bd-873f-4bcf-9e02-ef1a00a4b2f5/6a1f1ef6-55bf-477c-8dd0-2fc8a23a09c0/ADAPTATION.md). Deployment and publishing remain platform steps.","treeHash":"87cedf43afd10607b670f2a7d7a5ba3378f049c1","usage":{"cachedInputTokens":2992640,"inputTokens":165769,"model":"gpt-6-astra","outputTokens":30641,"runtime":"codex","turns":7,"wallClockMs":946683}},{"artifacts":[],"attempt":1,"bundleHash":"eae9280240b421f1c154537c71ad6e04db1e9013f89bd80d933fff99abff4a19","device":"68fd8dd6450ac70c","findings":[],"hash":"807277430058ee0d47dd883ac6ff00d1384ce22311371899228de53c61fe1145","nodeId":"c7d7a525-fd0a-423b-98dc-f05970bebd42","outcome":"completed","summary":"Updated only `launch.json`, preserving the accepted constructor values and deployment order: Stacker, then ProjectRegistry. Corrected notes to match the implementation.\n\nValidation passed: manifest checks, compiled ABI matching, and `forge build`. `forge test`: 94 passed, 0 failed, 7 optional fork tests skipped.","treeHash":"257a7e6b4433d5760f0209a1c4164506ef130707","usage":{"cachedInputTokens":289024,"inputTokens":52226,"model":"gpt-6-astra","outputTokens":4125,"runtime":"codex","turns":4,"wallClockMs":126864}},{"artifacts":[],"attempt":1,"bundleHash":"148212ab8ec4d87cf51eb23ee5535a251b3c2faaafa7b02ce0a1994943466b62","device":"6a7dea7fd5378a40","findings":[],"hash":"8e60751ee6a5d7d0ed8d3e88781d70e71bc7052f7ee2c64a1b393241d0d1f000","nodeId":"c7d7a525-fd0a-423b-98dc-f05970bebd42","outcome":"completed","summary":"Updated only `launch.json` notes to reflect the accepted registry protections and reused vault risks. Preserved deployment order and all constructor arguments.\n\nValidation passed:\n- Manifest schema and compiled constructor ABIs match.\n- `forge build` passed.\n- `forge test`: 112 passed, 0 failed, 7 optional fork tests skipped.","treeHash":"ebf090ee4b7e1d19beeb51ed26a7ea87e3a1413f","usage":{"cachedInputTokens":346112,"inputTokens":87208,"model":"gpt-6-astra","outputTokens":4194,"runtime":"codex","turns":4,"wallClockMs":134392}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"1507f63d3f1b973a","findings":[{"citation":"resolved","description":"Control-flow gap between challenge() and onOracleResult(). challenge() snapshots p.beneficiary into the question text (line 249) and the panel judges that wallet under the 'beneficiary' definition. setBeneficiary() only checks `listed` and the caller, not `p.ask == Ask.None`, so the beneficiary can be rewritten while the question is in flight. onOracleResult() then reads p.beneficiary again (line 327) and pays the bond to the new wallet, and the record keeps a beneficiary no panel ever judged, with the challenge consumed. Every other interleaving on an open question is blocked (applyListing and challenge revert AskOpen); this is the one state write left open mid-operation. Impact is bounded: the bond is the project's own money and the switch is something the beneficiary could do before or after the challenge, so this is a consistency defect in the operation's atomicity, not a loss of funds. Minimal fix that preserves the design: revert in setBeneficiary while p.ask != Ask.None, or snapshot the beneficiary at challenge time and pay that one.","line":396,"path":"src/ProjectRegistry.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ProjectRegistry} from \"src/ProjectRegistry.sol\";\nimport {OracleAttestation} from \"src/oracle/OracleAttestation.sol\";\nimport {MockIntake, MintableIMD, MockProject} from \"test/mocks/MockIntake.sol\";\n\n/// @dev Fails on the current code: the beneficiary can be swapped while a challenge is open, so the\n/// bond of the defended challenge is paid to a wallet the panel never judged. Passes once the\n/// registry either refuses `setBeneficiary` while a question is open or pays the beneficiary that\n/// the challenge question named.\ncontract BeneficiaryMidChallengeTest is Test {\n    uint256 internal constant SIGNER_KEY = 0xA11CE;\n    uint256 internal constant BOND = 5e18;\n\n    MockIntake internal intake;\n    MintableIMD internal imd;\n    ProjectRegistry internal reg;\n    address internal project;\n    address internal judged = makeAddr(\"judgedBeneficiary\");\n    address internal swapped = makeAddr(\"swappedBeneficiary\");\n    address internal applicant = makeAddr(\"applicant\");\n    address internal challenger = makeAddr(\"challenger\");\n\n    function setUp() public {\n        vm.roll(1_000);\n        vm.warp(1_700_000_000);\n        intake = new MockIntake();\n        imd = new MintableIMD();\n        reg = new ProjectRegistry(address(intake), address(imd), address(0x57AC), vm.addr(SIGNER_KEY), 1, BOND, 1 hours);\n        project = address(new MockProject());\n        imd.mint(applicant, 100e18);\n        imd.mint(challenger, 100e18);\n        vm.prank(applicant);\n        imd.approve(address(reg), type(uint256).max);\n        vm.prank(challenger);\n        imd.approve(address(reg), type(uint256).max);\n    }\n\n    function _answer(bytes32 id, bool yes) internal returns (bool) {\n        OracleAttestation.Attestation memory a;\n        a.requestId = keccak256(abi.encode(\"uuid\", id));\n        a.chainId = 1;\n        a.answerType = OracleAttestation.ANSWER_BOOL;\n        a.answer = abi.encode(yes);\n        a.panelSize = 15;\n        a.quorum = 11;\n        a.agreed = 13;\n        a.issuedAt = uint64(block.timestamp);\n        a.expiresAt = uint64(block.timestamp + 1 days);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_KEY, reg.attestationDigest(a));\n        return intake.deliver(id, a, abi.encodePacked(r, s, v), 200_000);\n    }\n\n    function test_defendedBondGoesToTheBeneficiaryThePanelJudged() public {\n        vm.prank(applicant);\n        bytes32 id = reg.applyListing(project, \"PLEA\", \"https://github.com/khaed1/plea\", 50, judged);\n        assertTrue(_answer(id, true));\n        assertTrue(reg.isListed(project));\n\n        vm.warp(block.timestamp + 1 hours);\n        vm.prank(challenger);\n        id = reg.challenge(project, \"It credits the owner's wallet outside trades.\");\n\n        // While the question (which names `judged`) is open, the beneficiary hands the record over.\n        vm.prank(judged);\n        (bool ok,) = address(reg).call(abi.encodeCall(reg.setBeneficiary, (project, swapped)));\n        ok; // the fix may refuse this call or let it through and snapshot; either is accepted here\n\n        assertTrue(_answer(id, true), \"defended\");\n        assertTrue(reg.isListed(project));\n        assertEq(imd.balanceOf(judged), BOND, \"bond must reach the beneficiary the panel judged\");\n        assertEq(imd.balanceOf(swapped), 0, \"an unjudged wallet must not take the bond\");\n    }\n}","reproduction":"Mock intake, bond 5e18, cooldown 1h. 1) applicant calls applyListing(project, \"PLEA\", \"https://github.com/khaed1/plea\", 50, B1); intake delivers a signed yes -> listed, beneficiary B1. 2) warp +1h; challenger calls challenge(project, reason) -> question text names B1; bond 5e18 held by the registry. 3) B1 calls setBeneficiary(project, B2) -> succeeds (no AskOpen check). 4) intake delivers a signed yes for the challenge. Actual: Defended, imd.balanceOf(B2) == 5e18, imd.balanceOf(B1) == 0, projectOf(project).beneficiary == B2. Expected: either step 3 reverts while the question is open, or the bond goes to B1, the beneficiary the panel's answer was about. Proof test: test/scratch/BeneficiaryMidChallenge.t.sol fails on the current code with 'bond must reach the beneficiary the panel judged: 0 != 5000000000000000000'.","severity":"low","snippet":"        if (!p.listed) revert NotListed();\n        if (msg.sender != p.beneficiary) revert NotBeneficiary();","title":"setBeneficiary is allowed while a challenge is open, so a defended challenge pays its bond to a wallet the panel never judged"},{"citation":"resolved","description":"p.rateBps is written once, in applyListing, and never again while the project is listed (the only other write is the next applyListing, which requires `listed == false`). challengeQuestion() tells the panel 'It is listed at a cashback rate of <p.rateBps> basis points' and the 'rate' definition requires that '<r> must be the rate in force now'. The definitions explicitly allow a project whose rate can change as long as it stays within 25-100 bps, but the registry has no way to restate the rate: no setRate ask, and applyListing reverts AlreadyListed. So a listed project that moves its rate from 50 to 75 bps (both allowed) is bound to fail the rate rule on any challenge, and the only way to re-state the rate is to be delisted first (losing the listing period and paying two more oracle fees). Design limitation of the control flow rather than a bug the panel can see, but it is a concrete state in which the contract's own rules and its question text contradict each other. Fix options: let the beneficiary open a rate-restatement ask (an Apply-like question that keeps the listing), or make the challenge question ask only that the rate is within 25-100 bps and name the stated rate as informational.","line":249,"path":"src/ProjectRegistry.sol","reproduction":"1) applyListing(project, name, url, 50, B) answered yes -> projectOf(project).rateBps == 50, listed. 2) The project's owner changes its on-chain cashback rate to 75 bps (allowed by the 'rate' definition). 3) There is no function that updates rateBps while listed: setBeneficiary only changes the beneficiary; applyListing(project, ..., 75, B) reverts AlreadyListed. 4) challenge(project, \"rate is now 75\") sends challengeQuestion(project, reason, 50, B), which reads 'It is listed at a cashback rate of 50 basis points' and the definition '... and 50 must be the rate in force now.' A panel following the definitions must answer false -> Delisted. Expected: a listed project with a rate still inside 25-100 bps has a way to restate it without losing its listing.","severity":"low","snippet":"            project, p, _challengeBody(project, reason, p.rateBps, p.beneficiary), challengeBond","title":"A challenge restates the rate recorded at application and there is no path to update it, so a project that lawfully changes its rate is delisted on its next challenge"},{"citation":"resolved","description":"applyListing is permissionless and a project can have one open ask at a time. A third party can front-run the team's application with wrong terms (another beneficiary, another rate), the panel answers no, and the slot reopens only after the answer or after PENDING_EXPIRY (1 day) if the writer never answers; the griefer can repeat as soon as the slot opens. On Sepolia the oracle asset (0x44a1...f89a) is open-mint, so each cycle costs only gas. ADAPTATION.md records this as a retained limit of the approved 'anyone applies' design (imported finding 04f9947f...), so this row exists for coverage; no new mechanism is proposed here beyond that note.","line":222,"path":"src/ProjectRegistry.sol","reproduction":"1) griefer calls applyListing(project, \"x\", \"https://example.org/x\", 25, griefer) paying 0.5 IMD. 2) team calls applyListing(project, correct name, url, 50, team) -> reverts AskOpen. 3) after the panel's no (Rejected) or after expire(project) once 1 day passed, the griefer re-applies in the same block the slot opens; the team is again refused AskOpen. Expected per the brief: the team can apply for its own project; actual: the team can be kept out as long as the griefer keeps paying 0.5 IMD per cycle.","severity":"info","snippet":"        if (p.ask != Ask.None) revert AskOpen();","title":"One open question per project lets anyone occupy a project's application slot for up to a day per 0.5 IMD (documented design limit)"},{"citation":"resolved","description":"Cross-contract side effect: TestSIMD._beforeTokenTransfer sets lastDepositBlock[to] = block.number on every positive mint, and _withdraw reverts SameBlockRedeem while block.number == lastDepositBlock[owner]. Stacker.credit mints shares to an arbitrary `trader`, so any caller can stamp any holder for 1 wei of tIMD plus gas and block that holder's redeem/withdraw in the same block; repeated each block it delays the exit for as long as the griefer pays gas. The Stacker adds no capability the vault does not already expose through deposit(1, victim), and the vault is live and reused per the brief, so this is noted for the website builders and integrators (a redeem that reverts right after a credit is this, not a bug in their code), not as a change to the Stacker.","line":89,"path":"src/Stacker.sol","reproduction":"Fork or local TestSIMD at block N: victim holds tsIMD from a deposit at block N-1. Attacker, in block N before the victim's tx: imd.approve(stacker, 1); stacker.credit(victim, 1) -> lastDepositBlock[victim] = N. Victim's sImd.redeem(shares, victim, victim) in block N reverts SameBlockRedeem; maxRedeem(victim) reads 0. Expected: a 1-wei third-party credit should not change what the victim can do in that block; actual: it postpones the exit by one block, repeatable.","severity":"info","snippet":"        shares = SIMD.deposit(imdAmount, trader);","title":"credit(victim, 1 wei) stamps the victim's one-block vault hold, delaying its tsIMD redeem in that block (live vault behaviour, reused not redeployed)"}],"hash":"972f534a7cb0e685a9fb596be93743fd8bbc1332ecf15479ab781572c4ff014f","nodeId":"a3564024-b280-4a1c-9c1e-c9f0d9b60659","outcome":"completed","summary":"The review is complete. The findings file is on disk and valid, the source tree is unchanged, and no scratch files remain.\n\n**Outcome:** the control flow of both contracts holds up. I traced every listed entry point through its guards, state writes and failure paths against the Execution Trace, Periphery and First Principles checklists, and found no loss-of-funds or permanent-breakage defect. Four findings are recorded in `.imd-findings.json`, two low and two informational.\n\n**Findings**\n- **Low, with proof.** The beneficiary can be swapped while a challenge is open. The question names the old wallet, the panel judges it, and the bond of a defended challenge is paid to the new, unjudged wallet. Every other writer refuses an open question, so this is the one mid-operation state write left unguarded. The proof test fails on the current code and passes with a one-line guard.\n- **Low.** The challenge question restates the rate recorded at application and nothing can update it while listed. A project that lawfully moves its rate within 25 to 100 bps is bound to fail the rate rule on its next challenge.\n- **Info.** The documented one-open-question slot lets anyone occupy a project's application for up to a day per fee. Recorded for coverage since the author already accepted it.\n- **Info.** A 1-wei credit stamps the trader's one-block vault hold, delaying a same-block redeem. This is the live vault's behaviour, not the Stacker's, and is noted for the site and integrators.\n\n**What was verified beyond the code**\n- Live Sepolia reads confirmed the Intake price, writer-gated completion, 1M callback gas, the four-word `requests` getter the registry decodes in `expire`, and the vault's asset wiring and unpaused state.\n- The oracle body stays under every protocol limit: the longest question is 1045 bytes and every definition value is under 512.\n- The launch manifest has the right contracts, argument counts, order and schema keys.\n\n**Coverage:** all seven entry points have rows, plus three invariant rows. Three rows point at findings, the rest hold. Nothing was left unreached.","treeHash":null,"usage":{"cachedInputTokens":1462311,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":40656,"runtime":"claude","turns":32,"wallClockMs":625435}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"ca075d17c94a854b","findings":[{"citation":"resolved","description":"Only one question per project can be open (`AskOpen`), a defended challenge restarts `challengeCooldown`, and the bond of a defended challenge is paid to `p.beneficiary`. When the beneficiary (or any wallet it controls) is itself the challenger, the bond comes straight back to it, so a self-challenge costs only the 0.5 IMD oracle fee. By sending its own `challenge` the moment `challengeOpenAt` arrives (first in the block, or front-running a pending honest challenge in the mempool), the beneficiary keeps every honest challenger out: their transaction reverts `AskOpen` while the self-challenge is open, and `ChallengeTooSoon` for a whole new cooldown once the panel says yes. The panel then only ever sees the beneficiary's chosen [REASON] text, never the honest challenger's pointer to the violation. No funds are lost, but the challenge mechanism, the only way to delist, can be kept away from the public indefinitely at 0.5 IMD per cooldown (free on Sepolia, where the fee token is open-mint). A fix that keeps the agreed no-owner design: do not restart the cooldown on a defended challenge (or restart it only when challenger != beneficiary), and/or do not pay a defended bond to the beneficiary when the challenger is the beneficiary (burn it or send it to the Intake's treasury). Which of these is wanted is the author's scope decision.","line":316,"path":"src/ProjectRegistry.sol","reproduction":"State: project listed with beneficiary B, challengeBond 5e18, challengeCooldown 1 hour (the launch's 3600 s). Step 1: at block.timestamp == projectOf(project).challengeOpenAt, B calls challenge(project, \"routine check\") paying 5.5 IMD. Step 2: honest challenger H calls challenge(project, \"It credits the owner wallet outside trades.\") in the same block -> reverts AskOpen (expected: H's challenge is accepted or at least gets a turn). Step 3: the Intake delivers a signed yes (panelSize 15, quorum 11, agreed 11) -> Defended, 5e18 transferred to B, challengeOpenAt = now + 1 hour; H's challenge now reverts ChallengeTooSoon. Step 4: repeat from step 1 each hour. After 3 rounds B's net cost is exactly 3 * 0.5e18 and H has never been able to open a challenge. Verified with a Foundry test against MockIntake (test deleted; it mirrors test/ProjectRegistry.t.sol's fixture with the beneficiary as challenger).","severity":"low","snippet":"            if (challengeBond != 0) oracleAsset.safeTransfer(p.beneficiary, challengeBond);","title":"A project's beneficiary can hold the challenge slot forever for the price of the oracle fee"},{"citation":"resolved","description":"The registry pulls and approves exactly `ORACLE_FEE` and asks the constant `ACTION` with a constructor-fixed `oracleSigner`, and it has no owner. The live Intake v2 (source read from Sourcify, 0xa43e...de82 on Sepolia) lets its owner call `setPrice(action, asset, amount)` at any time: a higher price makes `requestWithFailure` revert `PriceNotMet`, and `setPrice(..., 0)` (how a version such as oracle-1 is retired for oracle-2) makes it revert `ActionNotSold`. From that moment `applyListing` and `challenge` revert forever. Every project listed at that moment stays `listed == true` with no way to delist it, since the only delisting path is a signed challenge answer; the same happens if the oracle signer key is rotated (every answer fails `BadSignature`, the fee is spent, and `expire` only returns bonds). The oracle-consumer reference says the intake, action, asset+price and signer must never be constants. The launch forbids post-deployment configuration and the brief wants no owner, so the ownerless choice is a design decision to record, but one part can be fixed without any owner: read the live price with `intake.priceOf(ACTION, oracleAsset)` at ask time and pull/approve that amount, so a price move does not stop the registry. design.md (\"Fixed oracle settings\") plans a redeploy; the indexer must then treat the old registry's listings as frozen, since nobody can ever delist them there.","line":81,"path":"src/ProjectRegistry.sol","reproduction":"State: registry wired to an Intake whose price for (ACTION, oracleAsset) is 0.5e18; project P listed; cooldown elapsed. Step 1: Intake owner calls setPrice(ACTION, oracleAsset, 0.6e18). Step 2: anyone calls challenge(P, \"It credits the owner wallet outside trades.\") -> reverts PriceNotMet(0.6e18, 0.5e18) (expected per the reference: the registry pays the current price). Step 3: Intake owner calls setPrice(ACTION, oracleAsset, 0). challenge(P, ...) and applyListing(Q, ...) revert ActionNotSold; isListed(P) stays true forever. Verified with a Foundry test using a mock Intake with a settable price (deleted). Live check 2026-10-11: priceOf(ACTION, 0x44a1...f89a) == 0.5e18 today, callbackGas == 1,000,000, owner 0x047F606fD5b2BaA5f5C6c4aB8958E45CB6B054B7 can change both.","severity":"low","snippet":"    uint256 public constant ORACLE_FEE = 0.5e18;","title":"Hard-coded oracle fee, action id and signer: a price move at the Intake bricks the registry and leaves listed projects unchallengeable"},{"citation":"resolved","description":"`applyListing` is open to anyone for any contract and one question per project may be open. A griefer who front-runs the real applicant's transaction with the same project but its own beneficiary and rate blocks the real application with `AskOpen` until the panel says no (minutes) or a day passes (`expire`), then repeats. Each attempt costs the griefer only the 0.5 IMD oracle fee, which on Sepolia is the open-mint test IMD, so it is free there. If the panel ever wrongly answers yes, the griefer's wallet becomes the beneficiary that holds the project's points and collects every defended bond, and the team can only undo that through a challenge after the cooldown. design.md lists this under \"Known limits\"; it is recorded here so the adapter decides whether an application by a non-beneficiary should be refused or rate-limited, with the trade-off that any gate needs some notion of who speaks for a project.","line":213,"path":"src/ProjectRegistry.sol","reproduction":"State: project P (a contract) not listed, no open ask. Step 1: griefer G calls applyListing(P, \"P\", \"https://example.org/x\", 100, G) and pays 0.5 IMD. Step 2: the real team T calls applyListing(P, \"P\", \"https://example.org/x\", 50, T) -> reverts AskOpen (expected: T's application is taken). Step 3: panel answers no -> Rejected; G immediately applies again; T's next attempt reverts AskOpen again. Verified with a Foundry test on MockIntake (deleted).","severity":"info","snippet":"        if (p.ask != Ask.None) revert AskOpen();","title":"Anyone can take a project's application slot ahead of its team with bogus terms (documented known limit)"},{"citation":"resolved","description":"Every registry test signs `reg.attestationDigest(a)` with its own key, so a struct, type string or domain that drifted from the oracle's would still pass the whole suite while every real answer failed `BadSignature` after the fee was spent. The oracle-consumer reference delivers a conformance test (vector chain 11155111, consumer 0x...2748, digest 0x95fefa8b..., a signature from the vector key) and says it is the one test that ties a consumer to what the oracle signs. I ran that vector against ProjectRegistry during this review: the digest matches, the callback selector is the canonical 0x510379c7, and the protocol's signature recovers to the vector signer, so there is no defect today; the gap is coverage against future edits to src/oracle/OracleAttestation.sol.","line":80,"path":"test/ProjectRegistry.t.sol","reproduction":"Change any field name in OracleAttestation.TYPEHASH (for example rename `agreed` to `agreedCount`) and run `forge test`: all 68 tests still pass, while deploying ProjectRegistry at 0x0000000000000000000000000000000000002748 on chain 11155111 and comparing attestationDigest(vector) to 0x95fefa8b7c529852f4e2b6aec888930eb2bf5078e6443a85808e36df19e1325c fails. Copy the reference's OracleConsumerConformanceTest with deployConsumer() deploying ProjectRegistry at VECTOR_CONSUMER (signer SIGNER, intake = caller()) and keep test_digestMatchesTheProtocol and test_callbackSelectorIsCanonical.","severity":"info","snippet":"        (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, reg.attestationDigest(a));","title":"No conformance test against the protocol's signed vector: the suite only verifies self-signed digests"},{"citation":"resolved","description":"On Sepolia the Stacker stakes TestIMD 0x2b69...1e82 (the `faucet()` token), while launch.json wires the registry's `oracleAsset` to IdentityMD's test IMD 0x44a1...f89a (\"Identity.md (test)\", open `mint(address,uint256)`), because the live Intake prices oracle.request only in that asset: priceOf(ACTION, 0x44a1...) == 0.5e18 and priceOf(ACTION, 0x2b69...) == 0 (read live 2026-10-11). This is the correct wiring, not a defect, but the brief's website flow (faucet, then apply or challenge from the same wallet) will fail unless the site also mints and approves 0x44a1...f89a for the registry. Recorded so the adapter and the site builder do not use the faucet balance for the fee.","line":256,"path":"src/ProjectRegistry.sol","reproduction":"Wallet W calls TestIMD(0x2b69...).faucet() (10,000 tIMD), approves the registry for tIMD, and calls applyListing(P, \"P\", \"https://example.org/x\", 50, W): reverts inside safeTransferFrom on 0x44a1...f89a with ERC20InsufficientAllowance / ERC20InsufficientBalance (expected by a site user: the application is sent). Minting 0.5e18 of 0x44a1...f89a to W and approving the registry makes the same call succeed.","severity":"info","snippet":"        oracleAsset.safeTransferFrom(msg.sender, address(this), ORACLE_FEE + bond);","title":"The registry's fee and bond token is not the faucet token the Stacker uses; the site must mint 0x44a1...f89a for apply and challenge"}],"hash":"b0a826cc4a7d66b9780eeb4014f03b6711c6da8b71d27a0c69accfc8ea97b716","nodeId":"09710c79-a5f3-43d4-b289-73675ce26f96","outcome":"completed","summary":"The review is complete. Findings are in `.imd-findings.json` at the repository root, with every snippet verified against its line; the scratch tests are removed and the tree is otherwise untouched.\n\n**Verdict: no critical, high or medium defects.** Two low findings, three informational notes.\n\n**What I read**\n- `src/Stacker.sol`, `src/ProjectRegistry.sol`, `src/oracle/OracleAttestation.sol`, the three mocks, all nine test files, `launch.json`, the design and listing docs, and the job brief.\n- The live Intake v2 on Sepolia, from its verified Sourcify source. Its `requests` getter, `requestWithFailure` and writer-only `complete` match what the registry assumes.\n- Live Sepolia state: TestSIMD's asset is TestIMD, it is unpaused, the Intake prices the action at 0.5 of token 0x44a1…f89a and at zero in TestIMD, and the callback gas is one million.\n- Could not reach: the on-chain verified sources of TestIMD, TestSIMD and 0x44a1…f89a. I relied on the repository's copies and live reads for those.\n\n**What I checked**\n- The 68-test suite passes, and both Sepolia fork suites pass against a public RPC.\n- The registry's EIP-712 digest and callback selector match the protocol's conformance vector, and the protocol's own signature recovers to the vector signer.\n- All three settle paths fit the mainnet 200k stipend from cold storage, worst case 129k.\n- The free oracle check accepts the question shape with no blockers, 888 seats online, quorum 11.\n- The manifest has only the schema keys, seven registry arguments in order, and notes of 1,171 characters.\n\n**Findings**\n- **Low:** a beneficiary can self-challenge at each cooldown, get its bond back and restart the cooldown, keeping honest challengers out at 0.5 IMD per round.\n- **Low:** the fee, action and signer are constants in an ownerless contract. A price move or retirement at the Intake stops every ask and leaves listed projects undelistable. Reading `priceOf` at ask time removes the price part without adding an owner.\n- **Info:** application-slot front-running, a known limit the author documents.\n- **Info:** no conformance test against the protocol vector, so a future drift in the attestation struct would pass the suite.\n- **Info:** the registry's fee token is not the faucet token, so the site must mint 0x44a1…f89a before apply or challenge.\n\nOne note for the adapter outside the findings: the registry's deploy costs about 4.3M gas because of its question strings, so the launch's gas ceiling should be checked against roughly 4.8M for both contracts.","treeHash":null,"usage":{"cachedInputTokens":3288834,"inputTokens":610,"model":"claude-fable-5-1","outputTokens":55035,"runtime":"claude","turns":57,"wallClockMs":796512}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e0f64c10e30e33e2","findings":[{"citation":"resolved","description":"credit is permissionless and accepts any non-zero amount, and trader is any address. TestSIMD stamps lastDepositBlock[to] on every positive mint (_beforeTokenTransfer) and _withdraw reverts SameBlockRedeem while block.number == lastDepositBlock[owner]; maxRedeem/maxWithdraw report 0. On the live vault, previewDeposit(1) = 1e6 shares (decimals offset 6), so a 1-wei credit always mints shares and passes the ZeroShares check. A griefer who front-runs a trader's redeem/withdraw with Stacker.credit(trader, 1) in the same block makes it revert, for 1 wei of the freely minted TestIMD plus gas. Repeating this in every block blocks the trader's exit for as long as the griefer keeps paying gas. The vault comments say a third party must not be able to stamp a hold on an account for free; the Stacker gives anyone a cheap, labelled way to do it, and each grief also emits a Stacked event that the site's leaderboards read. Root cause is shared: TestSIMD.deposit(1, victim) does the same directly, so a fix needs both contracts. Possible fixes: a minimum credit in the Stacker (it raises the cost only), and in the vault, stamping only when the receiver is the caller, or not letting third-party mints extend an existing holder's hold. Economic impact: no funds are lost, but the cashback trader's sIMD exit is delayed at the griefer's will.","line":89,"path":"src/Stacker.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\nimport \"forge-std/Test.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {Stacker, IStakedIMD} from \"src/Stacker.sol\";\nimport {TestIMD} from \"test/mocks/TestIMD.sol\";\nimport {TestSIMD} from \"test/mocks/TestSIMD.sol\";\ncontract HoldGriefTest is Test {\n    function test_dustCreditMustNotBlockTraderRedeem() public {\n        TestIMD imd = new TestIMD();\n        TestSIMD v = new TestSIMD(address(imd), address(this));\n        Stacker s = new Stacker(IERC20(address(imd)), IStakedIMD(address(v)));\n        address project = address(0xBEEF); address trader = address(0xCAFE); address griefer = address(0xBAD);\n        deal(address(imd), project, 100e18); deal(address(imd), griefer, 1);\n        vm.prank(project); imd.approve(address(s), type(uint256).max);\n        vm.prank(griefer); imd.approve(address(s), type(uint256).max);\n        vm.prank(project); uint256 sh = s.credit(trader, 10e18);\n        vm.roll(block.number + 100);\n        vm.prank(griefer); try s.credit(trader, 1) {} catch {}\n        vm.prank(trader);\n        v.redeem(sh, trader, trader); // reverts SameBlockRedeem today\n    }\n}","reproduction":"Live state checked on Sepolia: TestSIMD 0xf9e2...1cc1 previewDeposit(1) = 1000000 and it is not paused. Steps: (1) the project credits the trader 10e18, then roll 100 blocks; maxRedeem(trader) > 0. (2) In the same block as the trader's redeem, the griefer (holding 1 wei tIMD, with an approval to the Stacker) calls Stacker.credit(trader, 1); it returns shares > 0. (3) maxRedeem(trader) == 0 and trader.redeem(shares, trader, trader) reverts SameBlockRedeem. Expected: a third party cannot block a holder's exit for 1 wei. Actual: it can, in every block.","severity":"low","snippet":"        shares = SIMD.deposit(imdAmount, trader);","title":"Anyone can credit 1 wei to a trader to reset the TestSIMD one-block hold and block that trader's redeem"}],"hash":"bccb0672a4076e14bbf0d98ebb9dee1a35b2bb9aaddb88ef7c4ff6e39f9a760a","nodeId":"77b70cd9-78b3-4289-bcb9-4c2c506e8fd7","outcome":"completed","summary":"I found one low-severity defect in the economics of the Stacker and the ProjectRegistry, and nothing critical, high or medium. Findings and coverage are in `.imd-findings.json`; no repository files were changed, and the scratch test I ran is deleted.\n\n**Finding 1 (low): a 1-wei credit can stop any trader withdrawing in that block** (`src/Stacker.sol:89`)\n- **How:** anyone can call `credit(trader, 1)` for any trader. The live TestSIMD vault turns 1 wei into 1,000,000 shares, so the `ZeroShares` check passes and the vault's one-block hold is reset for that trader.\n- **Effect:** if this lands in the same block as the trader's `redeem`, the redeem reverts with `SameBlockRedeem`. It costs 1 wei of a free test token plus gas, can be repeated every block, and each attempt also puts a `Stacked` event on the site's leaderboards. No funds are lost, but the trader can't get out while someone keeps paying gas.\n- **Proof:** I reproduced it with the repo's TestIMD/TestSIMD mocks; the test is in the finding.\n- **Fix:** the root cause is in the reused vault, since calling `TestSIMD.deposit(1, victim)` directly does the same thing. A minimum credit in the Stacker only makes the grief more expensive; a real fix has to change how the vault sets its hold.\n\n**What holds:**\n- **Fees and bonds:** the registry pulls exactly the live fee and approves only that much for the Intake. It holds only the bonds of open challenges, and each bond is paid out exactly once: to the beneficiary on a \"yes\", to the challenger on a \"no\", a failure or an expiry.\n- **Answers:** only answers from the Intake, for the registry's own open request, are accepted. They must carry a valid signature, be fresh, and come from a panel of at least 15 with 11 agreeing.\n- **`expire`:** I checked the live Intake v2 on Sepolia. Its `requests()` returns (payer, target, selector, completed) in exactly the order `expire` reads it.\n- **Question size:** with the largest allowed inputs, the question is at most 1,051 bytes, under the oracle's 2,000 limit.\n- **Tests:** the existing suite passes (95 tests; I skipped the fork tests).\n\nI left these out as findings because the design notes already accept them:\n- Anyone can grab a project's application or challenge slot first, at 0.5 IMD per round.\n- A beneficiary can challenge its own project and only loses the fee.\n- The oracle signer and the Intake are fixed, so changing either means deploying a new registry.\n- Bonds are paid in a test token anyone can mint, so on Sepolia they don't deter anyone.\n\n**Coverage:** every entry point has a row: `credit` points to the finding, and the six registry functions plus the bond-balance invariant are marked holds.","treeHash":null,"usage":{"cachedInputTokens":1549190,"inputTokens":42,"model":"claude-opus-5-5","outputTokens":22057,"runtime":"claude","turns":23,"wallClockMs":282912}},{"artifacts":[],"attempt":1,"bundleHash":"078ebfcd7f7b21bf24388673a4cb644f77ecf2cd602cbda3714c46833f0228e4","device":"fd4958ee1ca0d1f2","findings":[],"hash":"f4a978d3a9153226a2810e9e1c7d2c301524417a770a4a4500f4b1bd7a8e6853","nodeId":"ec753fa9-93ee-44fb-b33d-46a75db40b43","outcome":"completed","summary":"Updated the existing regression and invariant tests for beneficiary locking, permanent challenge pinning, and correct bond payouts.\n\nOffline `forge build` and `forge test` pass: **150 passed, 0 failed**. Seven optional RPC fork tests skipped.\n\nOnly `test/` files changed.","treeHash":"ebeb3a904190812cba117e1b9bd1be3d2e39c9a1","usage":{"cachedInputTokens":1429760,"inputTokens":111193,"model":"gpt-6-astra","outputTokens":8027,"runtime":"codex","turns":5,"wallClockMs":273838}}],"verification":[{"checks":[{"durationMs":8989,"exitCode":0,"name":"build","output":"Compiling 74 files with Solc 0.8.26\nSolc 0.8.26 finished in 8.88s\nCompiler run successful!\n","passed":true},{"durationMs":5276,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RegistrySepoliaFork.t.sol:RegistrySepoliaForkTest\n[SKIP] test_sepolia_applyPaysTheRealIntake_thenAnswerLists() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 520.24µs (60.87µs CPU time)\n\nRan 3 tests for test/SepoliaFork.t.sol:SepoliaForkTest\n[SKIP] test_sepolia_creditEventAndTotals() (gas: 0)\n[SKIP] test_sepolia_liveFacts() (gas: 0)\n[SKIP] test_sepolia_pausedVaultRevertsThenRecovers() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 645.62µs (144.02µs CPU time)\n\nRan 3 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_fork_creditNewThenRepeatTrader() (gas: 0)\n[SKIP] test_fork_liveFacts() (gas: 0)\n[SKIP] test_fork_oneBlockHoldThenRedeem() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 910.38µs (285.01µs CPU time)\n\nRan 1 test for test/FactoryRehearsal.t.sol:FactoryRehearsalTest\n[PASS] test_sepoliaFactoryDeploysBothInOrderOnAnEmptyChain() (gas: 419479)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.03ms (774.28µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdListingTest\n[PASS] test_coldApplicationYes_deliveredWithin200k() (gas: 140868)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.52ms (234.87µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDefenseTest\n[PASS] test_coldDefendedChallenge_deliveredWithin200k() (gas: 168148)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.61ms (159.11µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDelistingTest\n[PASS] test_coldDelistedChallenge_deliveredWithin200k() (gas: 152599)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.82ms (194.83µs CPU time)\n\nRan 5 tests for test/OracleConsumerConformance.t.sol:OracleConsumerConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 160001)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3671)\n[PASS] test_digestMatchesTheProtocol() (gas: 13627)\n[PASS] test_protocolSignaturePassesVerificationBeforePanelPolicy() (gas: 69596)\n[PASS] test_tamperingTheProtocolVectorFailsSignatureVerification() (gas: 64583)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 2.84ms (733.36µs CPU time)\n\nRan 3 tests for test/RegistryCallbackGas.t.sol:RegistryColdFailureTest\n[PASS] test_coldChallengeAfterDeadline_canExpire() (gas: 128285)\n[PASS] test_coldDisagreedChallenge_deliveredWithin200k() (gas: 140233)\n[PASS] test_coldRefusedChallenge_deliveredWithin200k() (gas: 140317)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 2.88ms (296.06µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdRejectionTest\n[PASS] test_coldApplicationNo_deliveredWithin200k() (gas: 135785)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.56ms (228.18µs CPU time)\n\nRan 20 tests for test/Stacker.t.sol:StackerTest\n[PASS] testFuzz_credit(address,uint256) (runs: 256, μ: 387944, ~: 387766)\nLogs:\n  Bound result 3103870551\n\n[PASS] testFuzz_credit_shortAllowanceAlwaysReverts(uint256,uint256) (runs: 256, μ: 367572, ~: 368837)\nLogs:\n  Bound result 3040185698315259129342\n  Bound result 1403857076218403515095\n\n[PASS] testFuzz_credit_twoTradersProportional(uint256,uint256) (runs: 256, μ: 430118, ~: 430206)\nLogs:\n  Bound result 92506154428405244755968\n  Bound result 21363\n\n[PASS] test_constructor_doesNotCallExistingVaultOrToken() (gas: 56037)\n[PASS] test_constructor_vaultWithoutCode_creditCannotMove() (gas: 131214)\n[PASS] test_constructor_wiringWithoutExternalCalls() (gas: 43846)\n[PASS] test_credit_manyProjectsAndTraders() (gas: 9371828)\n[PASS] test_credit_revertsOnShortAllowance() (gas: 378414)\n[PASS] test_credit_revertsOnShortBalance() (gas: 370521)\n[PASS] test_credit_revertsOnZeroShares() (gas: 383268)\n[PASS] test_credit_revertsWhenVaultPaused() (gas: 508017)\n[PASS] test_credit_sharesFollowVaultPrice() (gas: 617727)\n[PASS] test_credit_sharesGoOnlyToTrader() (gas: 374387)\n[PASS] test_credit_totalsAndEvent() (gas: 493973)\n[PASS] test_credit_zeroAmountReturnsZeroNoEvent() (gas: 80024)\n[PASS] test_credit_zeroTraderReverts() (gas: 66272)\n[PASS] test_failedFirstCredit_rollsBackApprovalAndRetriesValidation() (gas: 531558)\n[PASS] test_firstCredit_approvesOnce_andLaterCreditsStillWork() (gas: 397349)\n[PASS] test_firstCredit_revertsOnAssetMismatch() (gas: 791551)\n[PASS] test_integrator_tryCatchSurvivesPausedVault() (gas: 1053516)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 109.06ms (163.62ms CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_emptyChainRehearsal_constructorPasses() (gas: 25809)\n[PASS] test_launchManifest_knownShape() (gas: 31169)\n[PASS] test_registry_emptyChainRehearsal_constructorPasses() (gas: 7131620)\n[PASS] test_runtimeSizeAndNoEscapeOpcodes() (gas: 4217889)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 521.58ms (36.08ms CPU time)\n\nRan 10 tests for test/RegistryAuditRegression.t.sol:RegistryAuditRegressionTest\n[PASS] testFuzz_applicationPaysCurrentPrice(uint96) (runs: 256, μ: 2282346, ~: 2282180)\nLogs:\n  Bound result 16870884524521\n\n[PASS] test_defendedChallengeFromAnotherWalletDoesNotRenewImmunity() (gas: 6666301)\n[PASS] test_defendedSelfChallengeDoesNotRenewImmunity() (gas: 15564501)\n[PASS] test_permissionlessApplicantCanOccupySlotUntilRejected() (gas: 4520315)\n[PASS] test_priceRiseAndFall_preserveBondAndExactPayment() (gas: 6856024)\n[PASS] test_retiredActionApplicationMovesNothing() (gas: 278791)\n[PASS] test_retiredActionRefusesBeforePaymentAndPreservesListing() (gas: 4667017)\n[PASS] test_signedAnswerMustReachItsOwnQuorum() (gas: 2375956)\n[PASS] test_stakingFaucetTokenCannotPayOracleFee() (gas: 3478238)\n[PASS] test_staleExactApprovalCannotSpendAnUnexpectedPriceIncrease() (gas: 342811)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 521.37ms (541.60ms CPU time)\n\nRan 23 tests for test/ProjectRegistry.t.sol:ProjectRegistryTest\n[PASS] testFuzz_apply_nameIsSafeOrRefused(bytes) (runs: 256, μ: 201701, ~: 55462)\n[PASS] testFuzz_apply_rate(uint16) (runs: 256, μ: 389083, ~: 47467)\n[PASS] test_answer_freshnessAndPanelChecks() (gas: 2706878)\n[PASS] test_answer_mustBeSignedByTheOracleForThisContract() (gas: 2395797)\n[PASS] test_answer_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2383855)\n[PASS] test_apply_bodyIsTheOracleBody() (gas: 2401211)\n[PASS] test_apply_oneOpenQuestionAtATime_andNotWhenListed() (gas: 2380895)\n[PASS] test_apply_paysExactlyTheFeeAndAsks() (gas: 2293636)\n[PASS] test_apply_validation() (gas: 562562)\n[PASS] test_callbackOutOfGas_isRecoverableThroughExpire() (gas: 4414475)\n[PASS] test_challenge_defended_bondToBeneficiary_noNewCooldown() (gas: 4601594)\n[PASS] test_challenge_failureOrExpiry_returnsTheBond_projectStaysListed() (gas: 6732327)\n[PASS] test_challenge_lost_delistsFromThisBlock_bondBack() (gas: 6736374)\n[PASS] test_challenge_onlyListed_afterCooldown_oneAtATime() (gas: 4560242)\n[PASS] test_challenge_paysFeeAndBond_bodyNamesTheReason() (gas: 4643848)\n[PASS] test_constructor_rejectsZeroAddresses() (gas: 6519)\n[PASS] test_constructor_wiring() (gas: 73967)\n[PASS] test_expire_afterADay_orWhenTheIntakeCompletedWithoutAnAnswer() (gas: 4468138)\n[PASS] test_failure_clearsTheApplication_andNeverLists() (gas: 4342324)\n[PASS] test_failure_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2233769)\n[PASS] test_no_rejects_andTheProjectCanApplyAgain() (gas: 4481573)\n[PASS] test_setBeneficiary_onlyTheBeneficiaryOfAListedProject() (gas: 2427879)\n[PASS] test_yes_listsFromThisBlock() (gas: 2314729)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 521.47ms (241.62ms CPU time)\n\nRan 7 tests for test/StackerExternalCalls.t.sol:StackerExternalCallsTest\n[PASS] testFuzz_creditMatchesDirectDepositFromSameVaultState(uint96,uint96,uint96) (runs: 1000, μ: 976810, ~: 976766)\nLogs:\n  Bound result 99999218129895936625778\n  Bound result 62514264337593543158054\n  Bound result 146478197617355118\n\n[PASS] testFuzz_lateFailureRollsBackAllEffects(uint96,bool,bool) (runs: 1000, μ: 2934853, ~: 2930169)\nLogs:\n  Bound result 3\n\n[PASS] test_anotherCallersApprovalCannotBeSpent() (gas: 598484)\n[PASS] test_noReturnTokenStillMovesExactAssetsAndShares() (gas: 3117568)\n[PASS] test_oneWeiLateRevertRollsBackFirstApproval() (gas: 2937399)\n[PASS] test_tokenReentryDuringApprovalAndPullCannotCreateExtraCashback() (gas: 3738536)\n[PASS] test_zeroShareReturnRollsBackAnActualMint() (gas: 2925677)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 533.80ms (1.05s CPU time)\n\nRan 20 tests for test/RegistryAdversarial.t.sol:RegistryAdversarialTest\n[PASS] testFuzz_nonCanonicalBoolCannotDelist(uint256) (runs: 1000, μ: 4816484, ~: 4816446)\nLogs:\n  Bound result 8146\n\n[PASS] testFuzz_oldCallbacksCannotCloseReplacementApplication(uint8) (runs: 1000, μ: 4962606, ~: 4976547)\nLogs:\n  Bound result 2\n\n[PASS] testFuzz_pendingDeadlineStillAllowsAnswerButNotExpiry(bool,bool) (runs: 1000, μ: 3689408, ~: 2588957)\n[PASS] testFuzz_shortBoolEncodingCannotReleaseBond(uint8) (runs: 1000, μ: 4695364, ~: 4695107)\nLogs:\n  Bound result 9\n\n[PASS] test_answerBeforeAskToleranceHasExactBoundary() (gas: 2569294)\n[PASS] test_attestationExpiryIsInclusive() (gas: 2559697)\n[PASS] test_beneficiaryHandoverRevokesOldWalletDuringOpenChallenge() (gas: 4621121)\n[PASS] test_challengeCooldownHasExactBoundary() (gas: 4672733)\n[PASS] test_challengeShortAllowanceCannotBorrowDonatedFunds() (gas: 2742643)\n[PASS] test_emptyAndMalformedSignaturesCannotSettle() (gas: 3345454)\n[PASS] test_everySignedFieldIsAuthenticatedBeforeABondCanMove() (gas: 8856950)\n[PASS] test_futureIssuedAtToleranceHasExactBoundary() (gas: 2560044)\n[PASS] test_intakeRevertRollsBackFeeBondApprovalAndOpenRecord() (gas: 4924904)\n[PASS] test_maximumFeeAdditionRevertsWithoutChangingListing() (gas: 2679248)\n[PASS] test_oldChallengeCannotRefundTwiceOrCloseNewChallenge() (gas: 7284246)\n[PASS] test_oneSecondAfterDeadlineCannotReleaseBondToBeneficiary() (gas: 4823146)\n[PASS] test_signatureForSameAddressOnAnotherChainCannotReleaseBond() (gas: 4814543)\n[PASS] test_starvedChallengeCallbackRefundsOnlyChallenger() (gas: 4820178)\n[PASS] test_thirdPartyPaidQuestionCannotListOurProject() (gas: 2781336)\n[PASS] test_tokenReturningFalseCannotCreatePaidRequest() (gas: 2689336)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 533.77ms (2.11s CPU time)\n\nRan 19 tests for test/StackerEdges.t.sol:StackerEdgesTest\n[PASS] testFuzz_credit_pausedAlwaysRevertsAndMovesNothing(address,uint256) (runs: 1000, μ: 229791, ~: 229562)\nLogs:\n  Bound result 1000000000000000000000000\n\n[PASS] testFuzz_credit_repeatedCyclesExtractNoDust(uint256,uint8) (runs: 1000, μ: 1527839, ~: 1370521)\nLogs:\n  Bound result 10\n\n[PASS] testFuzz_credit_shortBalanceAlwaysReverts(uint256,uint256) (runs: 1000, μ: 388739, ~: 388707)\nLogs:\n  Bound result 521654724004317291866334\n  Bound result 373442508437325148212707\n\n[PASS] testFuzz_credit_thenRedeem_noFreeProfit(uint256,uint256,uint256) (runs: 1000, μ: 742666, ~: 761716)\nLogs:\n  Bound result 73183961435648305925605\n  Bound result 100000000000000000000000\n  Bound result 95112992550768386140526\n\n[PASS] testFuzz_credit_traderValueWithinOneShareOfAmount(uint256,uint256,uint256) (runs: 1000, μ: 683190, ~: 688814)\nLogs:\n  Bound result 93964262626553030070463\n  Bound result 98272292886126585639947\n  Bound result 65726797\n\n[PASS] testFuzz_credit_zeroSharesGuardTracksVaultPreview(uint256,uint256) (runs: 1000, μ: 490860, ~: 510495)\nLogs:\n  Bound result 9785390957607971053\n  Bound result 724004317291866334\n\n[PASS] test_credit_allowanceConsumedExactly_secondCallReverts() (gas: 615593)\n[PASS] test_credit_astronomicalButRepresentable() (gas: 365161)\n[PASS] test_credit_balanceConsumedExactly_secondCallReverts() (gas: 591023)\n[PASS] test_credit_eventMatchesReturnAndBalanceDeltaAtNonUnitPrice() (gas: 662705)\n[PASS] test_credit_maxUint_revertsCleanlyInVaultMath() (gas: 238830)\n[PASS] test_credit_oneWei() (gas: 361738)\n[PASS] test_credit_pausedBeatsShortAllowance_nothingPulled() (gas: 468463)\n[PASS] test_credit_projectIsTrader_countedOnBothSides() (gas: 326667)\n[PASS] test_credit_reentrancyFromVaultIsBlocked() (gas: 736980)\n[PASS] test_credit_zeroAmountWhilePaused_returnsZeroWithoutTouchingVault() (gas: 91064)\n[PASS] test_credit_zeroTraderWhilePaused_stillZeroTrader() (gas: 89528)\n[PASS] test_credit_zeroTraderWithShortAllowance_stillZeroTrader() (gas: 285166)\n[PASS] test_strayImdInStacker_isNeverSpentByCredit() (gas: 522294)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 533.87ms (2.29s CPU time)\n\nRan 8 tests for test/RegistryBodyProperties.t.sol:RegistryBodyPropertiesTest\n[PASS] testFuzz_applicationBodyRoundTripsValidText(bytes32,uint8,uint8,uint16) (runs: 1000, μ: 2668596, ~: 2627866)\nLogs:\n  Bound result 35\n  Bound result 131\n  Bound result 25\n\n[PASS] testFuzz_challengeBodyRoundTripsValidText(bytes32,uint16) (runs: 1000, μ: 4909611, ~: 4850345)\nLogs:\n  Bound result 20\n\n[PASS] test_applicationMaximumTextAndRate() (gas: 2907216)\n[PASS] test_applicationMinimumTextAndRate() (gas: 2549989)\n[PASS] test_challengeMaximumReason() (gas: 5245102)\n[PASS] test_challengeMinimumReason() (gas: 4746208)\n[PASS] test_everyForbiddenByteIsRejectedInEveryUserTextFieldBeforePayment() (gas: 52091176)\n[PASS] test_textLengthsJustOutsideLimitsAreAtomic() (gas: 2894415)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 533.87ms (989.09ms CPU time)\n\nRan 2 tests for test/ProjectRegistryInvariant.t.sol:ProjectRegistryInvariantTest\n[PASS]\nProjectRegistryInvariantTest invariants:\n[PASS] invariant_holdsOnlyOpenBonds\n[PASS] invariant_listingCounts\n[PASS] invariant_recordsConsistent\n ProjectRegistryInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-----------------+-------------------+-------+---------+----------╮\n| Contract        | Selector          | Calls | Reverts | Discards |\n+==================================================================+\n| RegistryHandler | answer            | 258   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | applyFor          | 250   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | challengeFor      | 245   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | completeAndExpire | 281   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | expireStale       | 240   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | failFor           | 251   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | handOver          | 272   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | passTime          | 251   | 0       | 0        |\n╰-----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 166502\n  Bound result 12011\n  Bound result 171515\n  Bound result 100\n  Bound result 87\n  Bound result 18172\n  Bound result 66\n  Bound result 10012\n  Bound result 27201\n  Bound result 80\n\n[PASS] test_handlerReachesEveryOutcome() (gas: 13759505)\nLogs:\n  Bound result 50\n  Bound result 25\n  Bound result 100\n  Bound result 172800\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 632.70ms (634.50ms CPU time)\n\nRan 1 test for test/StackerInvariant.t.sol:StackerInvariantTest\n[PASS]\nStackerInvariantTest invariants:\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_totalsConsistent\n[PASS] invariant_vaultConservation\n StackerInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭----------------+-------------+-------+---------+----------╮\n| Contract       | Selector    | Calls | Reverts | Discards |\n+===========================================================+\n| StackerHandler | advance     | 395   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | credit      | 409   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | donate      | 375   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | redeem      | 441   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | togglePause | 428   | 0       | 0        |\n╰----------------+-------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10\n  Bound result 2\n  Bound result 99412287581115007282\n  Bound result 555031684735789571806\n  Bound result 942013180460416016137\n  Bound result 8\n  Bound result 317\n  Bound result 64\n  Bound result 307822848697\n  Bound result 600000000000000000\n  Bound result 280\n  Bound result 11\n  Bound result 1\n  Bound result 26\n  Bound result 114823492287045508\n  Bound result 10\n  Bound result 400\n  Bound result 10\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 716.36ms (712.67ms CPU time)\n\nRan 2 tests for test/StackerInvariantExtended.t.sol:StackerInvariantExtendedTest\n[PASS]\nStackerInvariantExtendedTest invariants:\n[PASS] invariant_imdSupplyConservation\n[PASS] invariant_pauseAndOwnershipStateMachine\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_stackerTotals\n[PASS] invariant_vaultConservation\n[PASS] invariant_vaultSolvent\n StackerInvariantExtendedTest invariants (runs: 128, calls: 6144, reverts: 0)\n\n╭-----------------+----------------+-------+---------+----------╮\n| Contract        | Selector       | Calls | Reverts | Discards |\n+===============================================================+\n| ExtendedHandler | advance        | 436   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | credit         | 493   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | creditTiny     | 443   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | depositDirect  | 487   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | donate         | 493   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | faucet         | 494   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | redeem         | 479   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | renounce       | 476   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | rescue         | 491   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | setAllowance   | 468   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | togglePause    | 462   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | transferShares | 451   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | withdraw       | 471   | 0       | 0        |\n╰-----------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 3600\n  Bound result 32421\n  Bound result 180920\n  Bound result 282\n  Bound result 97\n  Bound result 53156\n  Bound result 195\n  Bound result 31\n  Bound result 9995000000000000000000\n  Bound result 1453\n  Bound result 18214\n  Bound result 5482\n  Bound result 16649\n  Bound result 91\n  Bound result 5\n  Bound result 31097787094515767893726\n  Bound result 1\n  Bound result 1000000\n  Bound result 19422\n  Bound result 24576\n  Bound result 34239629\n  Bound result 11\n  Bound result 20000000000000000000\n  Bound result 4164308733461230676\n  Bound result 2978809448330502113551\n  Bound result 244\n  Bound result 4999999999999999999999\n  Bound result 927\n  Bound result 14\n  Bound result 12648\n  Bound result 14\n  Bound result 74\n  Bound result 659918\n\n[PASS] test_handlerReachesEveryCreditOutcome() (gas: 4540137)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 5\n  Bound result 100000000000000000000\n  Bound result 1\n  Bound result 50000000000000000000\n  Bound result 7\n  Bound result 24000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 10000000000000000000\n  Bound result 1000000000000000000000\n  Bound result 372757101\n  Bound result 684498244\n  Bound result 1000000000000000000\n  Bound result 2949193105425070115\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.42s (4.42s CPU time)\n\nRan 2 tests for test/RegistryAccountingInvariant.t.sol:RegistryAccountingInvariantTest\n[PASS]\nRegistryAccountingInvariantTest invariants:\n[PASS] invariant_eachActorGetsExactlyTheirEntitlement\n[PASS] invariant_requestsAndListingsMatchIndependentHistory\n RegistryAccountingInvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭---------------------------+----------------------+-------+---------+----------╮\n| Contract                  | Selector             | Calls | Reverts | Discards |\n+===============================================================================+\n| RegistryAccountingHandler | ask                  | 2086  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | donate               | 2019  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | expire               | 2004  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | handOver             | 1984  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | passTime             | 2059  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | reprice              | 2085  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | settle               | 2018  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | unauthorizedOrReplay | 2129  | 0       | 0        |\n╰---------------------------+----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 0\n  Bound result 29\n  Bound result 9299\n  Bound result 172800\n  Bound result 64\n  Bound result 172800\n  Bound result 83\n  Bound result 21671\n  Bound result 22\n  Bound result 95\n  Bound result 5\n  Bound result 26\n  Bound result 24\n  Bound result 264337593543950334\n  Bound result 97\n  Bound result 5\n  Bound result 991585498770525458\n  Bound result 18207\n  Bound result 24789\n  Bound result 98\n  Bound result 3\n  Bound result 1\n  Bound result 20075\n  Bound result 20\n  Bound result 337886715139878004\n  Bound result 996\n  Bound result 22636\n  Bound result 15523\n  Bound result 91\n  Bound result 16353\n  Bound result 3788\n  Bound result 47\n  Bound result 55\n  Bound result 3\n  Bound result 26\n  Bound result 298\n  Bound result 1345113061112264049\n  Bound result 1313\n  Bound result 3\n  Bound result 83\n  Bound result 1\n  Bound result 88\n  Bound result 28\n  Bound result 48\n  Bound result 61\n  Bound result 94566\n\n[PASS] test_handlerReachesAllPayoutsAndChecksAfterEachTransition() (gas: 29810605)\nLogs:\n  Bound result 25\n  Bound result 1\n  Bound result 100\n  Bound result 0\n  Bound result 50\n  Bound result 0\n  Bound result 50\n  Bound result 1\n  Bound result 50\n  Bound result 0\n  Bound result 50\n  Bound result 2\n  Bound result 50\n  Bound result 3\n  Bound result 50\n  Bound result 4\n  Bound result 50\n  Bound result 172800\n  Bound result 1\n  Bound result 0\n  Bound result 50\n  Bound result 123\n  Bound result 0\n  Bound result 50\n  Bound result 1\n  Bound result 50\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 5.15s (5.15s CPU time)\n\nRan 22 test suites in 5.15s (14.75s CPU time): 131 tests passed, 0 failed, 7 skipped (138 total tests)\n","passed":true},{"durationMs":66,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ProjectRegistry.applyListing(address,string,string,uint16,address)\",\"ProjectRegistry.challenge(address,string)\",\"ProjectRegistry.expire(address)\",\"ProjectRegistry.onOracleFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"ProjectRegistry.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"ProjectRegistry.setBeneficiary(address,address)\",\"Stacker.credit(address,uint256)\"],\"files\":{\".github/ISSUE_TEMPLATE/listing-application.yml\":88,\".gitignore\":4,\"ADAPTATION.md\":65,\"NEXT_SESSION.md\":35,\"README.md\":227,\"docs/design.md\":295,\"docs/explainer.html\":247,\"docs/history.md\":89,\"docs/listing.md\":96,\"foundry.toml\":26,\"jobs/1-sepolia-launch.md\":23,\"jobs/2-sepolia-site.md\":18,\"jobs/3-list-plea.md\":21,\"jobs/4-mainnet-launch.md\":16,\"jobs/5-sepolia-v2-launch.md\":12,\"jobs/5-sepolia-v2-site.md\":10,\"jobs/requests/3-list-plea.json\":10,\"jobs/requests/4-mainnet-launch.json\":31,\"jobs/requests/5-sepolia-v2-launch-only.json\":31,\"jobs/requests/5-sepolia-v2-workflow.json\":50,\"launch.json\":25,\"listings/sepolia.json\":1,\"remappings.txt\":3,\"site/README.md\":57,\"site/app.mjs\":275,\"site/configure.mjs\":13,\"site/core.mjs\":221,\"site/index.html\":59,\"site/style.css\":1,\"site/test/app.test.mjs\":105,\"site/test/browser.mjs\":111,\"site/test/core.test.mjs\":115,\"site/test/fixture.mjs\":83,\"site/test/vendor/linkedom-0.18.12.mjs\":12761,\"site/test/vendor/linkedom-LICENSE\":15,\"site/vendor/ethers-6.17.0.mjs\":1,\"site/vendor/ethers-LICENSE.md\":21,\"src/ProjectRegistry.sol\":547,\"src/Stacker.sol\":98,\"src/oracle/OracleAttestation.sol\":265,\"test/ADVERSARIAL_COVERAGE.md\":34,\"test/Base.t.sol\":58,\"test/Deployment.t.sol\":99,\"test/FactoryRehearsal.t.sol\":47,\"test/MainnetFork.t.sol\":102,\"test/OracleConsumerConformance.t.sol\":140,\"test/ProjectRegistry.t.sol\":587,\"test/ProjectRegistryInvariant.t.sol\":233,\"test/RegistryAccountingInvariant.t.sol\":453,\"test/RegistryAdversarial.t.sol\":432,\"test/RegistryAuditRegression.t.sol\":154,\"test/RegistryBodyProperties.t.sol\":208,\"test/RegistryCallbackGas.t.sol\":111,\"test/RegistrySepoliaFork.t.sol\":111,\"test/SepoliaFork.t.sol\":88,\"test/Stacker.t.sol\":419,\"test/StackerEdges.t.sol\":390,\"test/StackerExternalCalls.t.sol\":257,\"test/StackerInvariant.t.sol\":148,\"test/StackerInvariantExtended.t.sol\":495,\"test/mocks/MockIntake.sol\":108,\"test/mocks/TestIMD.sol\":41,\"test/mocks/TestSIMD.sol\":178},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"2cd1cdaa416f88eb87a8d3cc63ce099b9bf7a2257ffaba98ac2765014a0b7a22","verifiedTreeHash":"cbc12c2cb1e440131a0c250fff68cb7c09ef6691","verifierVersion":"0.1.0+0e08a464"},{"checks":[{"durationMs":5994,"exitCode":0,"name":"build","output":"Compiling 70 files with Solc 0.8.26\nSolc 0.8.26 finished in 5.91s\nCompiler run successful!\n","passed":true},{"durationMs":3686,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RegistrySepoliaFork.t.sol:RegistrySepoliaForkTest\n[SKIP] test_sepolia_applyPaysTheRealIntake_thenAnswerLists() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 267.08µs (48.53µs CPU time)\n\nRan 3 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_fork_creditNewThenRepeatTrader() (gas: 0)\n[SKIP] test_fork_liveFacts() (gas: 0)\n[SKIP] test_fork_oneBlockHoldThenRedeem() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 364.99µs (174.43µs CPU time)\n\nRan 3 tests for test/SepoliaFork.t.sol:SepoliaForkTest\n[SKIP] test_sepolia_creditEventAndTotals() (gas: 0)\n[SKIP] test_sepolia_liveFacts() (gas: 0)\n[SKIP] test_sepolia_pausedVaultRevertsThenRecovers() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 609.86µs (214.09µs CPU time)\n\nRan 1 test for test/FactoryRehearsal.t.sol:FactoryRehearsalTest\n[PASS] test_sepoliaFactoryDeploysBothInOrderOnAnEmptyChain() (gas: 419479)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 825.99µs (564.92µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdRejectionTest\n[PASS] test_coldApplicationNo_deliveredWithin200k() (gas: 135785)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.52ms (161.56µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdListingTest\n[PASS] test_coldApplicationYes_deliveredWithin200k() (gas: 140868)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.37ms (184.26µs CPU time)\n\nRan 5 tests for test/OracleConsumerConformance.t.sol:OracleConsumerConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 160001)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3671)\n[PASS] test_digestMatchesTheProtocol() (gas: 13627)\n[PASS] test_protocolSignaturePassesVerificationBeforePanelPolicy() (gas: 69596)\n[PASS] test_tamperingTheProtocolVectorFailsSignatureVerification() (gas: 64583)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.51ms (748.05µs CPU time)\n\nRan 3 tests for test/RegistryCallbackGas.t.sol:RegistryColdFailureTest\n[PASS] test_coldChallengeAfterDeadline_canExpire() (gas: 128285)\n[PASS] test_coldDisagreedChallenge_deliveredWithin200k() (gas: 140233)\n[PASS] test_coldRefusedChallenge_deliveredWithin200k() (gas: 140317)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 2.00ms (184.26µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDefenseTest\n[PASS] test_coldDefendedChallenge_deliveredWithin200k() (gas: 168148)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.35ms (234.20µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDelistingTest\n[PASS] test_coldDelistedChallenge_deliveredWithin200k() (gas: 152599)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.45ms (337.63µs CPU time)\n\nRan 20 tests for test/Stacker.t.sol:StackerTest\n[PASS] testFuzz_credit(address,uint256) (runs: 256, μ: 387819, ~: 387750)\nLogs:\n  Bound result 335599011075229074258367\n\n[PASS] testFuzz_credit_shortAllowanceAlwaysReverts(uint256,uint256) (runs: 256, μ: 367940, ~: 368861)\nLogs:\n  Bound result 5000000000000000000\n  Bound result 15\n\n[PASS] testFuzz_credit_twoTradersProportional(uint256,uint256) (runs: 256, μ: 430205, ~: 430218)\nLogs:\n  Bound result 15\n  Bound result 5000000000000000000\n\n[PASS] test_constructor_doesNotCallExistingVaultOrToken() (gas: 56037)\n[PASS] test_constructor_vaultWithoutCode_creditCannotMove() (gas: 131214)\n[PASS] test_constructor_wiringWithoutExternalCalls() (gas: 43846)\n[PASS] test_credit_manyProjectsAndTraders() (gas: 9371828)\n[PASS] test_credit_revertsOnShortAllowance() (gas: 378414)\n[PASS] test_credit_revertsOnShortBalance() (gas: 370521)\n[PASS] test_credit_revertsOnZeroShares() (gas: 383268)\n[PASS] test_credit_revertsWhenVaultPaused() (gas: 508017)\n[PASS] test_credit_sharesFollowVaultPrice() (gas: 617727)\n[PASS] test_credit_sharesGoOnlyToTrader() (gas: 374387)\n[PASS] test_credit_totalsAndEvent() (gas: 493973)\n[PASS] test_credit_zeroAmountReturnsZeroNoEvent() (gas: 80024)\n[PASS] test_credit_zeroTraderReverts() (gas: 66272)\n[PASS] test_failedFirstCredit_rollsBackApprovalAndRetriesValidation() (gas: 531558)\n[PASS] test_firstCredit_approvesOnce_andLaterCreditsStillWork() (gas: 397349)\n[PASS] test_firstCredit_revertsOnAssetMismatch() (gas: 791551)\n[PASS] test_integrator_tryCatchSurvivesPausedVault() (gas: 1053516)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 171.73ms (292.17ms CPU time)\n\nRan 10 tests for test/RegistryAuditRegression.t.sol:RegistryAuditRegressionTest\n[PASS] testFuzz_applicationPaysCurrentPrice(uint96) (runs: 256, μ: 2282370, ~: 2282180)\nLogs:\n  Bound result 1383\n\n[PASS] test_defendedChallengeFromAnotherWalletDoesNotRenewImmunity() (gas: 6666301)\n[PASS] test_defendedSelfChallengeDoesNotRenewImmunity() (gas: 15564501)\n[PASS] test_permissionlessApplicantCanOccupySlotUntilRejected() (gas: 4520315)\n[PASS] test_priceRiseAndFall_preserveBondAndExactPayment() (gas: 6856024)\n[PASS] test_retiredActionApplicationMovesNothing() (gas: 278791)\n[PASS] test_retiredActionRefusesBeforePaymentAndPreservesListing() (gas: 4667017)\n[PASS] test_signedAnswerMustReachItsOwnQuorum() (gas: 2375956)\n[PASS] test_stakingFaucetTokenCannotPayOracleFee() (gas: 3478238)\n[PASS] test_staleExactApprovalCannotSpendAnUnexpectedPriceIncrease() (gas: 342811)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 171.82ms (192.40ms CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_emptyChainRehearsal_constructorPasses() (gas: 25809)\n[PASS] test_launchManifest_knownShape() (gas: 31169)\n[PASS] test_registry_emptyChainRehearsal_constructorPasses() (gas: 7131620)\n[PASS] test_runtimeSizeAndNoEscapeOpcodes() (gas: 4217889)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 171.99ms (21.26ms CPU time)\n\nRan 23 tests for test/ProjectRegistry.t.sol:ProjectRegistryTest\n[PASS] testFuzz_apply_nameIsSafeOrRefused(bytes) (runs: 256, μ: 192214, ~: 55509)\n[PASS] testFuzz_apply_rate(uint16) (runs: 256, μ: 264095, ~: 47467)\n[PASS] test_answer_freshnessAndPanelChecks() (gas: 2706878)\n[PASS] test_answer_mustBeSignedByTheOracleForThisContract() (gas: 2395797)\n[PASS] test_answer_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2383855)\n[PASS] test_apply_bodyIsTheOracleBody() (gas: 2401211)\n[PASS] test_apply_oneOpenQuestionAtATime_andNotWhenListed() (gas: 2380895)\n[PASS] test_apply_paysExactlyTheFeeAndAsks() (gas: 2293636)\n[PASS] test_apply_validation() (gas: 562562)\n[PASS] test_callbackOutOfGas_isRecoverableThroughExpire() (gas: 4414475)\n[PASS] test_challenge_defended_bondToBeneficiary_noNewCooldown() (gas: 4601594)\n[PASS] test_challenge_failureOrExpiry_returnsTheBond_projectStaysListed() (gas: 6732327)\n[PASS] test_challenge_lost_delistsFromThisBlock_bondBack() (gas: 6736374)\n[PASS] test_challenge_onlyListed_afterCooldown_oneAtATime() (gas: 4560242)\n[PASS] test_challenge_paysFeeAndBond_bodyNamesTheReason() (gas: 4643848)\n[PASS] test_constructor_rejectsZeroAddresses() (gas: 6519)\n[PASS] test_constructor_wiring() (gas: 73967)\n[PASS] test_expire_afterADay_orWhenTheIntakeCompletedWithoutAnAnswer() (gas: 4468138)\n[PASS] test_failure_clearsTheApplication_andNeverLists() (gas: 4342324)\n[PASS] test_failure_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2233769)\n[PASS] test_no_rejects_andTheProjectCanApplyAgain() (gas: 4481573)\n[PASS] test_setBeneficiary_onlyTheBeneficiaryOfAListedProject() (gas: 2427879)\n[PASS] test_yes_listsFromThisBlock() (gas: 2314729)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 172.02ms (356.59ms CPU time)\n\nRan 19 tests for test/StackerEdges.t.sol:StackerEdgesTest\n[PASS] testFuzz_credit_pausedAlwaysRevertsAndMovesNothing(address,uint256) (runs: 1000, μ: 229784, ~: 229562)\nLogs:\n  Bound result 166701257887196121320065\n\n[PASS] testFuzz_credit_repeatedCyclesExtractNoDust(uint256,uint8) (runs: 1000, μ: 1527611, ~: 1369861)\nLogs:\n  Bound result 1\n\n[PASS] testFuzz_credit_shortBalanceAlwaysReverts(uint256,uint256) (runs: 1000, μ: 388737, ~: 388695)\nLogs:\n  Bound result 200000000000000000\n  Bound result 100000000000000000\n\n[PASS] testFuzz_credit_thenRedeem_noFreeProfit(uint256,uint256,uint256) (runs: 1000, μ: 742519, ~: 761740)\nLogs:\n  Bound result 84546674667569931779997\n  Bound result 62288953042309289762173\n  Bound result 99999999999999999999998\n\n[PASS] testFuzz_credit_traderValueWithinOneShareOfAmount(uint256,uint256,uint256) (runs: 1000, μ: 683823, ~: 688814)\nLogs:\n  Bound result 101\n  Bound result 25299328580912191671212\n  Bound result 2631991883\n\n[PASS] testFuzz_credit_zeroSharesGuardTracksVaultPreview(uint256,uint256) (runs: 1000, μ: 491087, ~: 510483)\nLogs:\n  Bound result 4995\n  Bound result 659918\n\n[PASS] test_credit_allowanceConsumedExactly_secondCallReverts() (gas: 615593)\n[PASS] test_credit_astronomicalButRepresentable() (gas: 365161)\n[PASS] test_credit_balanceConsumedExactly_secondCallReverts() (gas: 591023)\n[PASS] test_credit_eventMatchesReturnAndBalanceDeltaAtNonUnitPrice() (gas: 662705)\n[PASS] test_credit_maxUint_revertsCleanlyInVaultMath() (gas: 238830)\n[PASS] test_credit_oneWei() (gas: 361738)\n[PASS] test_credit_pausedBeatsShortAllowance_nothingPulled() (gas: 468463)\n[PASS] test_credit_projectIsTrader_countedOnBothSides() (gas: 326667)\n[PASS] test_credit_reentrancyFromVaultIsBlocked() (gas: 736980)\n[PASS] test_credit_zeroAmountWhilePaused_returnsZeroWithoutTouchingVault() (gas: 91064)\n[PASS] test_credit_zeroTraderWhilePaused_stillZeroTrader() (gas: 89528)\n[PASS] test_credit_zeroTraderWithShortAllowance_stillZeroTrader() (gas: 285166)\n[PASS] test_strayImdInStacker_isNeverSpentByCredit() (gas: 522294)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 171.98ms (942.42ms CPU time)\n\nRan 1 test for test/StackerInvariant.t.sol:StackerInvariantTest\n[PASS]\nStackerInvariantTest invariants:\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_totalsConsistent\n[PASS] invariant_vaultConservation\n StackerInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭----------------+-------------+-------+---------+----------╮\n| Contract       | Selector    | Calls | Reverts | Discards |\n+===========================================================+\n| StackerHandler | advance     | 383   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | credit      | 418   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | donate      | 433   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | redeem      | 399   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | togglePause | 415   | 0       | 0        |\n╰----------------+-------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 274\n  Bound result 6126\n  Bound result 3\n  Bound result 684270961999835132733\n  Bound result 1\n  Bound result 269345559705708787923\n  Bound result 2827\n  Bound result 48\n  Bound result 10\n  Bound result 1647\n  Bound result 6283\n  Bound result 10\n  Bound result 4743\n  Bound result 661\n  Bound result 1\n  Bound result 1085\n  Bound result 10\n  Bound result 3\n  Bound result 2309\n  Bound result 14562\n  Bound result 12909\n  Bound result 312946193354399441160873\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 509.15ms (505.56ms CPU time)\n\nRan 2 tests for test/ProjectRegistryInvariant.t.sol:ProjectRegistryInvariantTest\n[PASS]\nProjectRegistryInvariantTest invariants:\n[PASS] invariant_holdsOnlyOpenBonds\n[PASS] invariant_listingCounts\n[PASS] invariant_recordsConsistent\n ProjectRegistryInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-----------------+-------------------+-------+---------+----------╮\n| Contract        | Selector          | Calls | Reverts | Discards |\n+==================================================================+\n| RegistryHandler | answer            | 279   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | applyFor          | 270   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | challengeFor      | 242   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | completeAndExpire | 251   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | expireStale       | 249   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | failFor           | 270   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | handOver          | 239   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | passTime          | 248   | 0       | 0        |\n╰-----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 78\n  Bound result 44\n  Bound result 71\n  Bound result 62\n  Bound result 78\n  Bound result 33\n  Bound result 102000\n  Bound result 138297\n  Bound result 45\n  Bound result 52\n\n[PASS] test_handlerReachesEveryOutcome() (gas: 13759505)\nLogs:\n  Bound result 50\n  Bound result 25\n  Bound result 100\n  Bound result 172800\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 534.88ms (539.12ms CPU time)\n\nRan 2 tests for test/StackerInvariantExtended.t.sol:StackerInvariantExtendedTest\n[PASS]\nStackerInvariantExtendedTest invariants:\n[PASS] invariant_imdSupplyConservation\n[PASS] invariant_pauseAndOwnershipStateMachine\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_stackerTotals\n[PASS] invariant_vaultConservation\n[PASS] invariant_vaultSolvent\n StackerInvariantExtendedTest invariants (runs: 128, calls: 6144, reverts: 0)\n\n╭-----------------+----------------+-------+---------+----------╮\n| Contract        | Selector       | Calls | Reverts | Discards |\n+===============================================================+\n| ExtendedHandler | advance        | 456   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | credit         | 503   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | creditTiny     | 494   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | depositDirect  | 464   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | donate         | 469   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | faucet         | 517   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | redeem         | 487   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | renounce       | 463   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | rescue         | 451   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | setAllowance   | 436   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | togglePause    | 473   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | transferShares | 450   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | withdraw       | 481   | 0       | 0        |\n╰-----------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10\n  Bound result 333000000000000000000\n  Bound result 2386898385408271088025\n  Bound result 800000000000000000\n  Bound result 1000000000000000000\n  Bound result 2\n  Bound result 1\n  Bound result 10954\n  Bound result 4\n  Bound result 1950\n  Bound result 24\n  Bound result 2127478271\n  Bound result 17681\n  Bound result 2275\n  Bound result 101\n  Bound result 4294967296\n  Bound result 3218\n  Bound result 976001\n  Bound result 19217\n  Bound result 10\n  Bound result 8948583674677671018222\n  Bound result 159\n  Bound result 2287\n  Bound result 3168\n  Bound result 896537714929858983515015190\n  Bound result 11015\n  Bound result 12\n  Bound result 20000000000000000000\n\n[PASS] test_handlerReachesEveryCreditOutcome() (gas: 4540137)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 5\n  Bound result 100000000000000000000\n  Bound result 1\n  Bound result 50000000000000000000\n  Bound result 7\n  Bound result 24000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 10000000000000000000\n  Bound result 1000000000000000000000\n  Bound result 372757101\n  Bound result 684498244\n  Bound result 1000000000000000000\n  Bound result 2949193105425070115\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 3.60s (3.60s CPU time)\n\nRan 18 test suites in 3.60s (5.52s CPU time): 94 tests passed, 0 failed, 7 skipped (101 total tests)\n","passed":true},{"durationMs":57,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ProjectRegistry.applyListing(address,string,string,uint16,address)\",\"ProjectRegistry.challenge(address,string)\",\"ProjectRegistry.expire(address)\",\"ProjectRegistry.onOracleFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"ProjectRegistry.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"ProjectRegistry.setBeneficiary(address,address)\",\"Stacker.credit(address,uint256)\"],\"files\":{\".github/ISSUE_TEMPLATE/listing-application.yml\":88,\".gitignore\":4,\"ADAPTATION.md\":65,\"NEXT_SESSION.md\":35,\"README.md\":227,\"docs/design.md\":295,\"docs/explainer.html\":247,\"docs/history.md\":89,\"docs/listing.md\":96,\"foundry.toml\":26,\"jobs/1-sepolia-launch.md\":23,\"jobs/2-sepolia-site.md\":18,\"jobs/3-list-plea.md\":21,\"jobs/4-mainnet-launch.md\":16,\"jobs/5-sepolia-v2-launch.md\":12,\"jobs/5-sepolia-v2-site.md\":10,\"jobs/requests/3-list-plea.json\":10,\"jobs/requests/4-mainnet-launch.json\":31,\"jobs/requests/5-sepolia-v2-launch-only.json\":31,\"jobs/requests/5-sepolia-v2-workflow.json\":50,\"launch.json\":25,\"listings/sepolia.json\":1,\"remappings.txt\":3,\"site/README.md\":57,\"site/app.mjs\":275,\"site/configure.mjs\":13,\"site/core.mjs\":221,\"site/index.html\":59,\"site/style.css\":1,\"site/test/app.test.mjs\":105,\"site/test/browser.mjs\":111,\"site/test/core.test.mjs\":115,\"site/test/fixture.mjs\":83,\"site/test/vendor/linkedom-0.18.12.mjs\":12761,\"site/test/vendor/linkedom-LICENSE\":15,\"site/vendor/ethers-6.17.0.mjs\":1,\"site/vendor/ethers-LICENSE.md\":21,\"src/ProjectRegistry.sol\":547,\"src/Stacker.sol\":98,\"src/oracle/OracleAttestation.sol\":265,\"test/Base.t.sol\":58,\"test/Deployment.t.sol\":99,\"test/FactoryRehearsal.t.sol\":47,\"test/MainnetFork.t.sol\":102,\"test/OracleConsumerConformance.t.sol\":140,\"test/ProjectRegistry.t.sol\":587,\"test/ProjectRegistryInvariant.t.sol\":233,\"test/RegistryAuditRegression.t.sol\":154,\"test/RegistryCallbackGas.t.sol\":111,\"test/RegistrySepoliaFork.t.sol\":111,\"test/SepoliaFork.t.sol\":88,\"test/Stacker.t.sol\":419,\"test/StackerEdges.t.sol\":390,\"test/StackerInvariant.t.sol\":148,\"test/StackerInvariantExtended.t.sol\":495,\"test/mocks/MockIntake.sol\":108,\"test/mocks/TestIMD.sol\":41,\"test/mocks/TestSIMD.sol\":178},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":1495,"exitCode":0,"name":"slither","output":"[medium/medium] unused-return at src/oracle/OracleAttestation.sol:171: OracleAttestationConsumer._verifyAttestation(OracleAttestation.Attestation,bytes) (src/oracle/OracleAttestation.sol#171-189) ignores return value by (recovered,err,None) = ECDSA.tryRecover(digest,signature) (src/oracle/OracleAttestation.sol#184)\n[medium/medium] unused-return at src/ProjectRegistry.sol:357: ProjectRegistry.expire(address) (src/ProjectRegistry.sol#357-366) ignores return value by (None,None,None,completed) = intake.requests(intakeId) (src/ProjectRegistry.sol#362)\n[low/medium] reentrancy-benign at src/Stacker.sol:71: Reentrancy in Stacker.credit(address,uint256) (src/Stacker.sol#71-97):\n[low/medium] reentrancy-benign at src/ProjectRegistry.sol:261: Reentrancy in ProjectRegistry._ask(address,ProjectRegistry.Project,string,uint256) (src/ProjectRegistry.sol#261-279):\n[low/medium] timestamp at src/ProjectRegistry.sol:357: ProjectRegistry.expire(address) (src/ProjectRegistry.sol#357-366) uses timestamp for comparisons\n[low/medium] timestamp at src/ProjectRegistry.sol:236: ProjectRegistry.challenge(address,string) (src/ProjectRegistry.sol#236-252) uses timestamp for comparisons\n[low/medium] timestamp at src/oracle/OracleAttestation.sol:171: OracleAttestationConsumer._verifyAttestation(OracleAttestation.Attestation,bytes) (src/oracle/OracleAttestation.sol#171-189) uses timestamp for comparisons\n[low/medium] timestamp at src/ProjectRegistry.sol:285: ProjectRegistry.onOracleResult(bytes32,OracleAttestation.Attestation,bytes) (src/ProjectRegistry.sol#285-335) uses timestamp for comparisons","passed":true},{"durationMs":422,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/Stacker.sol:80: Reentrancy: State change after external call (2 places)\n[low] internal-function-used-once at src/oracle/OracleAttestation.sol:209: Internal Function Used Only Once\n[low] require-revert-in-loop at src/ProjectRegistry.sol:540: Loop Contains `require`/`revert`\n[low] uninitialized-local-variable at src/ProjectRegistry.sol:540: Uninitialized Local Variable","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"6d4b0dea6a73e171dcdc57647c2e52c97bcde0c11a7e8748388dcbb74e77ca5d","verifiedTreeHash":"6d6cba5a717906e0c49fc1a8d17820480bc90983","verifierVersion":"0.1.0+0e08a464"},{"checks":[{"durationMs":6782,"exitCode":0,"name":"build","output":"Compiling 72 files with Solc 0.8.26\nSolc 0.8.26 finished in 6.69s\nCompiler run successful!\n","passed":true},{"durationMs":3889,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RegistrySepoliaFork.t.sol:RegistrySepoliaForkTest\n[SKIP] test_sepolia_applyPaysTheRealIntake_thenAnswerLists() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 461.42µs (63.06µs CPU time)\n\nRan 3 tests for test/SepoliaFork.t.sol:SepoliaForkTest\n[SKIP] test_sepolia_creditEventAndTotals() (gas: 0)\n[SKIP] test_sepolia_liveFacts() (gas: 0)\n[SKIP] test_sepolia_pausedVaultRevertsThenRecovers() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 431.72µs (107.25µs CPU time)\n\nRan 3 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_fork_creditNewThenRepeatTrader() (gas: 0)\n[SKIP] test_fork_liveFacts() (gas: 0)\n[SKIP] test_fork_oneBlockHoldThenRedeem() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 605.10µs (77.32µs CPU time)\n\nRan 1 test for test/FactoryRehearsal.t.sol:FactoryRehearsalTest\n[PASS] test_sepoliaFactoryDeploysBothInOrderOnAnEmptyChain() (gas: 419482)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 650.09µs (475.39µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdRejectionTest\n[PASS] test_coldApplicationNo_deliveredWithin200k() (gas: 156293)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.43ms (126.76µs CPU time)\n\nRan 2 tests for test/VaultTrustRegression.t.sol:VaultTrustRegressionTest\n[PASS] test_dustHoldThroughStackerAndDirectVault() (gas: 910410)\n[PASS] test_vaultOwnerCanSweepCashback() (gas: 637844)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.54ms (1.60ms CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDefenseTest\n[PASS] test_coldDefendedChallenge_deliveredWithin200k() (gas: 190529)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.91ms (124.40µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdListingTest\n[PASS] test_coldApplicationYes_deliveredWithin200k() (gas: 162651)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.86ms (303.32µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDelistingTest\n[PASS] test_coldDelistedChallenge_deliveredWithin200k() (gas: 171535)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.12ms (198.57µs CPU time)\n\nRan 3 tests for test/RegistryCallbackGas.t.sol:RegistryColdFailureTest\n[PASS] test_coldChallengeAfterDeadline_canExpire() (gas: 128234)\n[PASS] test_coldDisagreedChallenge_deliveredWithin200k() (gas: 140182)\n[PASS] test_coldRefusedChallenge_deliveredWithin200k() (gas: 140266)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 5.82ms (705.65µs CPU time)\n\nRan 10 tests for test/RegistryAuditRegression.t.sol:RegistryAuditRegressionTest\n[PASS] testFuzz_applicationPaysCurrentPrice(uint96) (runs: 256, μ: 2282667, ~: 2282481)\nLogs:\n  Bound result 3791676925750106\n\n[PASS] test_defendedChallengeFromAnotherWalletDoesNotRenewImmunity() (gas: 6841925)\n[PASS] test_defendedSelfChallengeDoesNotRenewImmunity() (gas: 16118511)\n[PASS] test_permissionlessApplicantCanOccupySlotUntilRejected() (gas: 4563271)\n[PASS] test_priceRiseAndFall_preserveBondAndExactPayment() (gas: 7058072)\n[PASS] test_retiredActionApplicationMovesNothing() (gas: 279090)\n[PASS] test_retiredActionRefusesBeforePaymentAndPreservesListing() (gas: 4760949)\n[PASS] test_signedAnswerMustReachItsOwnQuorum() (gas: 2398027)\n[PASS] test_stakingFaucetTokenCannotPayOracleFee() (gas: 3500658)\n[PASS] test_staleExactApprovalCannotSpendAnUnexpectedPriceIncrease() (gas: 343121)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 136.12ms (150.71ms CPU time)\n\nRan 5 tests for test/OracleConsumerConformance.t.sol:OracleConsumerConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 181781)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3671)\n[PASS] test_digestMatchesTheProtocol() (gas: 13664)\n[PASS] test_protocolSignaturePassesVerificationBeforePanelPolicy() (gas: 69567)\n[PASS] test_tamperingTheProtocolVectorFailsSignatureVerification() (gas: 64591)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 176.16ms (8.47ms CPU time)\n\nRan 20 tests for test/Stacker.t.sol:StackerTest\n[PASS] testFuzz_credit(address,uint256) (runs: 256, μ: 387960, ~: 387766)\nLogs:\n  Bound result 5000000000000000000\n\n[PASS] testFuzz_credit_shortAllowanceAlwaysReverts(uint256,uint256) (runs: 256, μ: 367580, ~: 368837)\nLogs:\n  Bound result 1000000\n  Bound result 755968\n\n[PASS] testFuzz_credit_twoTradersProportional(uint256,uint256) (runs: 256, μ: 430121, ~: 430206)\nLogs:\n  Bound result 92506154428405244755968\n  Bound result 1000000\n\n[PASS] test_constructor_doesNotCallExistingVaultOrToken() (gas: 56037)\n[PASS] test_constructor_vaultWithoutCode_creditCannotMove() (gas: 131214)\n[PASS] test_constructor_wiringWithoutExternalCalls() (gas: 43846)\n[PASS] test_credit_manyProjectsAndTraders() (gas: 9371828)\n[PASS] test_credit_revertsOnShortAllowance() (gas: 378414)\n[PASS] test_credit_revertsOnShortBalance() (gas: 370521)\n[PASS] test_credit_revertsOnZeroShares() (gas: 383268)\n[PASS] test_credit_revertsWhenVaultPaused() (gas: 508017)\n[PASS] test_credit_sharesFollowVaultPrice() (gas: 617727)\n[PASS] test_credit_sharesGoOnlyToTrader() (gas: 374387)\n[PASS] test_credit_totalsAndEvent() (gas: 493973)\n[PASS] test_credit_zeroAmountReturnsZeroNoEvent() (gas: 80024)\n[PASS] test_credit_zeroTraderReverts() (gas: 66272)\n[PASS] test_failedFirstCredit_rollsBackApprovalAndRetriesValidation() (gas: 531558)\n[PASS] test_firstCredit_approvesOnce_andLaterCreditsStillWork() (gas: 397349)\n[PASS] test_firstCredit_revertsOnAssetMismatch() (gas: 791551)\n[PASS] test_integrator_tryCatchSurvivesPausedVault() (gas: 1053516)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 195.53ms (242.57ms CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_emptyChainRehearsal_constructorPasses() (gas: 25809)\n[PASS] test_launchManifest_knownShape() (gas: 31169)\n[PASS] test_registry_emptyChainRehearsal_constructorPasses() (gas: 7587633)\n[PASS] test_runtimeSizeAndNoEscapeOpcodes() (gas: 4217889)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 223.00ms (60.91ms CPU time)\n\nRan 23 tests for test/ProjectRegistry.t.sol:ProjectRegistryTest\n[PASS] testFuzz_apply_nameIsSafeOrRefused(bytes) (runs: 256, μ: 201460, ~: 55509)\n[PASS] testFuzz_apply_rate(uint16) (runs: 256, μ: 214123, ~: 47467)\n[PASS] test_answer_freshnessAndPanelChecks() (gas: 2707488)\n[PASS] test_answer_mustBeSignedByTheOracleForThisContract() (gas: 2396222)\n[PASS] test_answer_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2405976)\n[PASS] test_apply_bodyIsTheOracleBody() (gas: 2401501)\n[PASS] test_apply_oneOpenQuestionAtATime_andNotWhenListed() (gas: 2403016)\n[PASS] test_apply_paysExactlyTheFeeAndAsks() (gas: 2293926)\n[PASS] test_apply_validation() (gas: 562562)\n[PASS] test_callbackOutOfGas_isRecoverableThroughExpire() (gas: 4415041)\n[PASS] test_challenge_defended_bondToBeneficiary_noNewCooldown() (gas: 4715447)\n[PASS] test_challenge_failureOrExpiry_returnsTheBond_projectStaysListed() (gas: 6892809)\n[PASS] test_challenge_lost_delistsFromThisBlock_bondBack() (gas: 6868886)\n[PASS] test_challenge_onlyListed_afterCooldown_oneAtATime() (gas: 4667316)\n[PASS] test_challenge_paysFeeAndBond_bodyNamesTheReason() (gas: 4741766)\n[PASS] test_constructor_rejectsZeroAddresses() (gas: 6519)\n[PASS] test_constructor_wiring() (gas: 74024)\n[PASS] test_expire_afterADay_orWhenTheIntakeCompletedWithoutAnAnswer() (gas: 4468682)\n[PASS] test_failure_clearsTheApplication_andNeverLists() (gas: 4342853)\n[PASS] test_failure_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2234015)\n[PASS] test_no_rejects_andTheProjectCanApplyAgain() (gas: 4524496)\n[PASS] test_setBeneficiary_onlyTheBeneficiaryOfAListedProject() (gas: 2472906)\n[PASS] test_yes_listsFromThisBlock() (gas: 2336847)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 222.97ms (390.88ms CPU time)\n\nRan 16 tests for test/RegistryRevisionRegression.t.sol:RegistryRevisionRegressionTest\n[PASS] testFuzz_answerIsConsumedAcrossApplications(bool) (runs: 256, μ: 6874196, ~: 6871099)\n[PASS] testFuzz_beneficiaryUnlocksAfterFailureOrExpiry(bool) (runs: 256, μ: 4670656, ~: 4664660)\n[PASS] testFuzz_challengeAllowsRateChangesWithinTheRules(uint16) (runs: 256, μ: 5437472, ~: 5437682)\nLogs:\n  Bound result 42\n\n[PASS] testFuzz_validCooldownCanList(uint64) (runs: 256, μ: 2416511, ~: 2416245)\nLogs:\n  Bound result 8228219\n\n[PASS] test_applicationAnswerCannotDefendAChallengeAndSpendItsBond() (gas: 4655586)\n[PASS] test_beneficiaryCannotTransferAfterChallengeDelists() (gas: 4655630)\n[PASS] test_challengeBodyLimitsAndConsumerDomain() (gas: 4987284)\n[PASS] test_constructorRefusesOverflowingAndExcessiveCooldowns() (gas: 16578)\n[PASS] test_invalidAnswerDoesNotConsumeUUID() (gas: 2477345)\n[PASS] test_legacyChallengeCannotChargeAfterAnyBeneficiaryHandoff() (gas: 9335977)\n[PASS] test_openChallengeLocksBeneficiaryAndDefendedBondDestination() (gas: 4992489)\n[PASS] test_pinnedChallengePreservesCooldownAndSlotRules() (gas: 4768551)\n[PASS] test_pinnedChallengeRefusesFrontrunBeforeAnyPayment() (gas: 5090415)\n[PASS] test_selfChallengeOccupiesSlotOnlyUntilItSettles() (gas: 6879117)\n[PASS] test_settingSameBeneficiaryDoesNotDisableLegacyChallenge() (gas: 4670015)\n[PASS] test_zeroAndMaximumCooldownCanList() (gas: 4743487)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 244.15ms (545.72ms CPU time)\n\nRan 19 tests for test/StackerEdges.t.sol:StackerEdgesTest\n[PASS] testFuzz_credit_pausedAlwaysRevertsAndMovesNothing(address,uint256) (runs: 1000, μ: 229771, ~: 229550)\nLogs:\n  Bound result 172800\n\n[PASS] testFuzz_credit_repeatedCyclesExtractNoDust(uint256,uint8) (runs: 1000, μ: 1553225, ~: 1370503)\nLogs:\n  Bound result 11\n\n[PASS] testFuzz_credit_shortBalanceAlwaysReverts(uint256,uint256) (runs: 1000, μ: 388746, ~: 388695)\nLogs:\n  Bound result 513384834687868127310656\n  Bound result 395917386431805386206\n\n[PASS] testFuzz_credit_thenRedeem_noFreeProfit(uint256,uint256,uint256) (runs: 1000, μ: 737195, ~: 761716)\nLogs:\n  Bound result 7456591936778010286\n  Bound result 68183004120522859204066\n  Bound result 76016864802941644577674\n\n[PASS] testFuzz_credit_traderValueWithinOneShareOfAmount(uint256,uint256,uint256) (runs: 1000, μ: 682682, ~: 688790)\nLogs:\n  Bound result 76128498454971992562576\n  Bound result 302\n  Bound result 100000000000000000000000\n\n[PASS] testFuzz_credit_zeroSharesGuardTracksVaultPreview(uint256,uint256) (runs: 1000, μ: 489478, ~: 510483)\nLogs:\n  Bound result 60328099137888\n  Bound result 52630744353886603\n\n[PASS] test_credit_allowanceConsumedExactly_secondCallReverts() (gas: 615593)\n[PASS] test_credit_astronomicalButRepresentable() (gas: 365161)\n[PASS] test_credit_balanceConsumedExactly_secondCallReverts() (gas: 591023)\n[PASS] test_credit_eventMatchesReturnAndBalanceDeltaAtNonUnitPrice() (gas: 662705)\n[PASS] test_credit_maxUint_revertsCleanlyInVaultMath() (gas: 238830)\n[PASS] test_credit_oneWei() (gas: 361738)\n[PASS] test_credit_pausedBeatsShortAllowance_nothingPulled() (gas: 468463)\n[PASS] test_credit_projectIsTrader_countedOnBothSides() (gas: 326667)\n[PASS] test_credit_reentrancyFromVaultIsBlocked() (gas: 736980)\n[PASS] test_credit_zeroAmountWhilePaused_returnsZeroWithoutTouchingVault() (gas: 91064)\n[PASS] test_credit_zeroTraderWhilePaused_stillZeroTrader() (gas: 89528)\n[PASS] test_credit_zeroTraderWithShortAllowance_stillZeroTrader() (gas: 285166)\n[PASS] test_strayImdInStacker_isNeverSpentByCredit() (gas: 522294)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 244.21ms (1.27s CPU time)\n\nRan 1 test for test/StackerInvariant.t.sol:StackerInvariantTest\n[PASS]\nStackerInvariantTest invariants:\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_totalsConsistent\n[PASS] invariant_vaultConservation\n StackerInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭----------------+-------------+-------+---------+----------╮\n| Contract       | Selector    | Calls | Reverts | Discards |\n+===========================================================+\n| StackerHandler | advance     | 389   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | credit      | 423   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | donate      | 416   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | redeem      | 412   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | togglePause | 408   | 0       | 0        |\n╰----------------+-------------+-------+---------+----------╯\n\nLogs:\n  Bound result 103976152839662004\n  Bound result 9774\n  Bound result 23180919986126374221171\n  Bound result 12615\n  Bound result 5\n  Bound result 2000\n  Bound result 5000000000000000000\n  Bound result 15\n  Bound result 5\n  Bound result 809663119454956953100562\n  Bound result 6\n  Bound result 1\n  Bound result 8\n  Bound result 634\n  Bound result 17708835561525880149089\n  Bound result 49063498041779236853575\n  Bound result 16384\n  Bound result 1\n  Bound result 101\n  Bound result 7\n  Bound result 5920\n  Bound result 1700000000\n  Bound result 999999999999999999001\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 552.71ms (548.63ms CPU time)\n\nRan 2 tests for test/ProjectRegistryInvariant.t.sol:ProjectRegistryInvariantTest\n[PASS]\nProjectRegistryInvariantTest invariants:\n[PASS] invariant_holdsOnlyOpenBonds\n[PASS] invariant_listingCounts\n[PASS] invariant_recordsConsistent\n ProjectRegistryInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-----------------+-------------------+-------+---------+----------╮\n| Contract        | Selector          | Calls | Reverts | Discards |\n+==================================================================+\n| RegistryHandler | answer            | 240   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | applyFor          | 275   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | challengeFor      | 261   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | completeAndExpire | 275   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | expireStale       | 225   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | failFor           | 240   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | handOver          | 282   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | passTime          | 250   | 0       | 0        |\n╰-----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 89600\n  Bound result 8281\n  Bound result 1137\n  Bound result 147200\n  Bound result 3\n\n[PASS] test_handlerReachesEveryOutcome() (gas: 14028842)\nLogs:\n  Bound result 50\n  Bound result 25\n  Bound result 100\n  Bound result 172800\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 575.14ms (576.01ms CPU time)\n\nRan 2 tests for test/StackerInvariantExtended.t.sol:StackerInvariantExtendedTest\n[PASS]\nStackerInvariantExtendedTest invariants:\n[PASS] invariant_imdSupplyConservation\n[PASS] invariant_pauseAndOwnershipStateMachine\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_stackerTotals\n[PASS] invariant_vaultConservation\n[PASS] invariant_vaultSolvent\n StackerInvariantExtendedTest invariants (runs: 128, calls: 6144, reverts: 0)\n\n╭-----------------+----------------+-------+---------+----------╮\n| Contract        | Selector       | Calls | Reverts | Discards |\n+===============================================================+\n| ExtendedHandler | advance        | 467   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | credit         | 505   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | creditTiny     | 441   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | depositDirect  | 482   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | donate         | 514   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | faucet         | 462   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | redeem         | 445   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | renounce       | 456   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | rescue         | 449   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | setAllowance   | 490   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | togglePause    | 438   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | transferShares | 496   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | withdraw       | 499   | 0       | 0        |\n╰-----------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 2\n  Bound result 11255\n  Bound result 6073\n  Bound result 1500000000000000000\n  Bound result 14952\n  Bound result 19658\n  Bound result 2\n  Bound result 2473148925\n  Bound result 2424357362\n  Bound result 8937\n  Bound result 2\n  Bound result 5\n  Bound result 6\n  Bound result 22236765365084607889075\n  Bound result 4711\n  Bound result 487393\n  Bound result 5098\n  Bound result 4608159314098578589955\n  Bound result 17793804969341057269579\n  Bound result 101\n  Bound result 128\n  Bound result 1898628659234950440036\n  Bound result 127\n\n[PASS] test_handlerReachesEveryCreditOutcome() (gas: 4540137)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 5\n  Bound result 100000000000000000000\n  Bound result 1\n  Bound result 50000000000000000000\n  Bound result 7\n  Bound result 24000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 10000000000000000000\n  Bound result 1000000000000000000000\n  Bound result 372757101\n  Bound result 684498244\n  Bound result 1000000000000000000\n  Bound result 2949193105425070115\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 3.79s (3.79s CPU time)\n\nRan 20 test suites in 3.80s (6.38s CPU time): 112 tests passed, 0 failed, 7 skipped (119 total tests)\n","passed":true},{"durationMs":66,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ProjectRegistry.applyListing(address,string,string,uint16,address)\",\"ProjectRegistry.challenge(address,string)\",\"ProjectRegistry.challengeForBeneficiary(address,string,address)\",\"ProjectRegistry.expire(address)\",\"ProjectRegistry.onOracleFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"ProjectRegistry.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"ProjectRegistry.setBeneficiary(address,address)\",\"Stacker.credit(address,uint256)\"],\"files\":{\".github/ISSUE_TEMPLATE/listing-application.yml\":88,\".gitignore\":4,\"ADAPTATION.md\":99,\"NEXT_SESSION.md\":35,\"README.md\":227,\"docs/design.md\":299,\"docs/explainer.html\":247,\"docs/history.md\":89,\"docs/listing.md\":96,\"foundry.toml\":26,\"jobs/1-sepolia-launch.md\":23,\"jobs/2-sepolia-site.md\":18,\"jobs/3-list-plea.md\":21,\"jobs/4-mainnet-launch.md\":16,\"jobs/5-sepolia-v2-launch.md\":12,\"jobs/5-sepolia-v2-site.md\":10,\"jobs/requests/3-list-plea.json\":10,\"jobs/requests/4-mainnet-launch.json\":31,\"jobs/requests/5-sepolia-v2-launch-only.json\":31,\"jobs/requests/5-sepolia-v2-workflow.json\":50,\"launch.json\":25,\"listings/sepolia.json\":1,\"remappings.txt\":3,\"site/README.md\":63,\"site/app.mjs\":280,\"site/configure.mjs\":13,\"site/core.mjs\":222,\"site/index.html\":61,\"site/style.css\":1,\"site/test/app.test.mjs\":142,\"site/test/browser.mjs\":111,\"site/test/core.test.mjs\":115,\"site/test/fixture.mjs\":97,\"site/test/vendor/linkedom-0.18.12.mjs\":12761,\"site/test/vendor/linkedom-LICENSE\":15,\"site/vendor/ethers-6.17.0.mjs\":1,\"site/vendor/ethers-LICENSE.md\":21,\"src/ProjectRegistry.sol\":607,\"src/Stacker.sol\":98,\"src/oracle/OracleAttestation.sol\":265,\"test/Base.t.sol\":58,\"test/Deployment.t.sol\":99,\"test/FactoryRehearsal.t.sol\":47,\"test/MainnetFork.t.sol\":102,\"test/OracleConsumerConformance.t.sol\":140,\"test/ProjectRegistry.t.sol\":587,\"test/ProjectRegistryInvariant.t.sol\":233,\"test/RegistryAuditRegression.t.sol\":157,\"test/RegistryCallbackGas.t.sol\":111,\"test/RegistryRevisionRegression.t.sol\":325,\"test/RegistrySepoliaFork.t.sol\":111,\"test/SepoliaFork.t.sol\":88,\"test/Stacker.t.sol\":419,\"test/StackerEdges.t.sol\":390,\"test/StackerInvariant.t.sol\":148,\"test/StackerInvariantExtended.t.sol\":495,\"test/VaultTrustRegression.t.sol\":41,\"test/mocks/MockIntake.sol\":108,\"test/mocks/TestIMD.sol\":41,\"test/mocks/TestSIMD.sol\":178},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":1618,"exitCode":0,"name":"slither","output":"[medium/medium] unused-return at src/oracle/OracleAttestation.sol:171: OracleAttestationConsumer._verifyAttestation(OracleAttestation.Attestation,bytes) (src/oracle/OracleAttestation.sol#171-189) ignores return value by (recovered,err,None) = ECDSA.tryRecover(digest,signature) (src/oracle/OracleAttestation.sol#184)\n[medium/medium] unused-return at src/ProjectRegistry.sol:392: ProjectRegistry.expire(address) (src/ProjectRegistry.sol#392-401) ignores return value by (None,None,None,completed) = intake.requests(intakeId) (src/ProjectRegistry.sol#397)\n[low/medium] reentrancy-benign at src/ProjectRegistry.sol:294: Reentrancy in ProjectRegistry._ask(address,ProjectRegistry.Project,string,uint256) (src/ProjectRegistry.sol#294-312):\n[low/medium] reentrancy-benign at src/Stacker.sol:71: Reentrancy in Stacker.credit(address,uint256) (src/Stacker.sol#71-97):\n[low/medium] timestamp at src/ProjectRegistry.sol:392: ProjectRegistry.expire(address) (src/ProjectRegistry.sol#392-401) uses timestamp for comparisons\n[low/medium] timestamp at src/ProjectRegistry.sol:267: ProjectRegistry._challenge(address,string,address) (src/ProjectRegistry.sol#267-285) uses timestamp for comparisons\n[low/medium] timestamp at src/oracle/OracleAttestation.sol:171: OracleAttestationConsumer._verifyAttestation(OracleAttestation.Attestation,bytes) (src/oracle/OracleAttestation.sol#171-189) uses timestamp for comparisons\n[low/medium] timestamp at src/ProjectRegistry.sol:318: ProjectRegistry.onOracleResult(bytes32,OracleAttestation.Attestation,bytes) (src/ProjectRegistry.sol#318-370) uses timestamp for comparisons","passed":true},{"durationMs":432,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/Stacker.sol:80: Reentrancy: State change after external call (2 places)\n[low] internal-function-used-once at src/oracle/OracleAttestation.sol:209: Internal Function Used Only Once\n[low] require-revert-in-loop at src/ProjectRegistry.sol:600: Loop Contains `require`/`revert`\n[low] uninitialized-local-variable at src/ProjectRegistry.sol:600: Uninitialized Local Variable\n[low] unused-public-function at src/ProjectRegistry.sol:444: Public Function Not Used Internally","passed":true},{"durationMs":1752,"exitCode":0,"name":"proof 959104138523","output":"Compiling 56 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.20s\nCompiler run successful!\n\nRan 1 test for test/imd-proof-3c29953f/Proof_959104138523.t.sol:BeneficiaryMidChallengeTest\n[PASS] test_defendedBondGoesToTheBeneficiaryThePanelJudged() (gas: 4667479)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.96ms (1.12ms CPU time)\n\nRan 1 test suite in 2.71ms (1.96ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"79abb0ffd0ffd59cb021977e1fcab4eb2bd863ae6f1b6b5b8f97a0c8972afc40","verifiedTreeHash":"87cedf43afd10607b670f2a7d7a5ba3378f049c1","verifierVersion":"0.1.0+0e08a464"},{"checks":[{"durationMs":6156,"exitCode":0,"name":"build","output":"Compiling 70 files with Solc 0.8.26\nSolc 0.8.26 finished in 6.06s\nCompiler run successful!\n","passed":true},{"durationMs":4088,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RegistrySepoliaFork.t.sol:RegistrySepoliaForkTest\n[SKIP] test_sepolia_applyPaysTheRealIntake_thenAnswerLists() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 393.60µs (38.78µs CPU time)\n\nRan 3 tests for test/SepoliaFork.t.sol:SepoliaForkTest\n[SKIP] test_sepolia_creditEventAndTotals() (gas: 0)\n[SKIP] test_sepolia_liveFacts() (gas: 0)\n[SKIP] test_sepolia_pausedVaultRevertsThenRecovers() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 414.59µs (63.46µs CPU time)\n\nRan 3 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_fork_creditNewThenRepeatTrader() (gas: 0)\n[SKIP] test_fork_liveFacts() (gas: 0)\n[SKIP] test_fork_oneBlockHoldThenRedeem() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 585.18µs (70.28µs CPU time)\n\nRan 1 test for test/FactoryRehearsal.t.sol:FactoryRehearsalTest\n[PASS] test_sepoliaFactoryDeploysBothInOrderOnAnEmptyChain() (gas: 419479)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 796.46µs (602.66µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdRejectionTest\n[PASS] test_coldApplicationNo_deliveredWithin200k() (gas: 135785)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.46ms (253.40µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdListingTest\n[PASS] test_coldApplicationYes_deliveredWithin200k() (gas: 140868)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.44ms (173.47µs CPU time)\n\nRan 5 tests for test/OracleConsumerConformance.t.sol:OracleConsumerConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 160001)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3671)\n[PASS] test_digestMatchesTheProtocol() (gas: 13627)\n[PASS] test_protocolSignaturePassesVerificationBeforePanelPolicy() (gas: 69596)\n[PASS] test_tamperingTheProtocolVectorFailsSignatureVerification() (gas: 64583)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.74ms (1.07ms CPU time)\n\nRan 3 tests for test/RegistryCallbackGas.t.sol:RegistryColdFailureTest\n[PASS] test_coldChallengeAfterDeadline_canExpire() (gas: 128285)\n[PASS] test_coldDisagreedChallenge_deliveredWithin200k() (gas: 140233)\n[PASS] test_coldRefusedChallenge_deliveredWithin200k() (gas: 140317)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 2.15ms (249.87µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDefenseTest\n[PASS] test_coldDefendedChallenge_deliveredWithin200k() (gas: 168148)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.08ms (358.89µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDelistingTest\n[PASS] test_coldDelistedChallenge_deliveredWithin200k() (gas: 152599)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.41ms (329.76µs CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_emptyChainRehearsal_constructorPasses() (gas: 25809)\n[PASS] test_launchManifest_knownShape() (gas: 31694)\n[PASS] test_registry_emptyChainRehearsal_constructorPasses() (gas: 7131620)\n[PASS] test_runtimeSizeAndNoEscapeOpcodes() (gas: 4217889)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 171.91ms (44.38ms CPU time)\n\nRan 23 tests for test/ProjectRegistry.t.sol:ProjectRegistryTest\n[PASS] testFuzz_apply_nameIsSafeOrRefused(bytes) (runs: 256, μ: 218740, ~: 55448)\n[PASS] testFuzz_apply_rate(uint16) (runs: 256, μ: 230763, ~: 47467)\n[PASS] test_answer_freshnessAndPanelChecks() (gas: 2706878)\n[PASS] test_answer_mustBeSignedByTheOracleForThisContract() (gas: 2395797)\n[PASS] test_answer_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2383855)\n[PASS] test_apply_bodyIsTheOracleBody() (gas: 2401211)\n[PASS] test_apply_oneOpenQuestionAtATime_andNotWhenListed() (gas: 2380895)\n[PASS] test_apply_paysExactlyTheFeeAndAsks() (gas: 2293636)\n[PASS] test_apply_validation() (gas: 562562)\n[PASS] test_callbackOutOfGas_isRecoverableThroughExpire() (gas: 4414475)\n[PASS] test_challenge_defended_bondToBeneficiary_noNewCooldown() (gas: 4601594)\n[PASS] test_challenge_failureOrExpiry_returnsTheBond_projectStaysListed() (gas: 6732327)\n[PASS] test_challenge_lost_delistsFromThisBlock_bondBack() (gas: 6736374)\n[PASS] test_challenge_onlyListed_afterCooldown_oneAtATime() (gas: 4560242)\n[PASS] test_challenge_paysFeeAndBond_bodyNamesTheReason() (gas: 4643848)\n[PASS] test_constructor_rejectsZeroAddresses() (gas: 6519)\n[PASS] test_constructor_wiring() (gas: 73967)\n[PASS] test_expire_afterADay_orWhenTheIntakeCompletedWithoutAnAnswer() (gas: 4468138)\n[PASS] test_failure_clearsTheApplication_andNeverLists() (gas: 4342324)\n[PASS] test_failure_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2233769)\n[PASS] test_no_rejects_andTheProjectCanApplyAgain() (gas: 4481573)\n[PASS] test_setBeneficiary_onlyTheBeneficiaryOfAListedProject() (gas: 2427879)\n[PASS] test_yes_listsFromThisBlock() (gas: 2314729)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 171.98ms (161.22ms CPU time)\n\nRan 20 tests for test/Stacker.t.sol:StackerTest\n[PASS] testFuzz_credit(address,uint256) (runs: 256, μ: 387864, ~: 387730)\nLogs:\n  Bound result 803504777604490361720622\n\n[PASS] testFuzz_credit_shortAllowanceAlwaysReverts(uint256,uint256) (runs: 256, μ: 367818, ~: 368825)\nLogs:\n  Bound result 890202195097775267815156\n  Bound result 132708138767164117933771\n\n[PASS] testFuzz_credit_twoTradersProportional(uint256,uint256) (runs: 256, μ: 430151, ~: 430194)\nLogs:\n  Bound result 89928461891782872549115\n  Bound result 2259\n\n[PASS] test_constructor_doesNotCallExistingVaultOrToken() (gas: 56037)\n[PASS] test_constructor_vaultWithoutCode_creditCannotMove() (gas: 131214)\n[PASS] test_constructor_wiringWithoutExternalCalls() (gas: 43846)\n[PASS] test_credit_manyProjectsAndTraders() (gas: 9371828)\n[PASS] test_credit_revertsOnShortAllowance() (gas: 378414)\n[PASS] test_credit_revertsOnShortBalance() (gas: 370521)\n[PASS] test_credit_revertsOnZeroShares() (gas: 383268)\n[PASS] test_credit_revertsWhenVaultPaused() (gas: 508017)\n[PASS] test_credit_sharesFollowVaultPrice() (gas: 617727)\n[PASS] test_credit_sharesGoOnlyToTrader() (gas: 374387)\n[PASS] test_credit_totalsAndEvent() (gas: 493973)\n[PASS] test_credit_zeroAmountReturnsZeroNoEvent() (gas: 80024)\n[PASS] test_credit_zeroTraderReverts() (gas: 66272)\n[PASS] test_failedFirstCredit_rollsBackApprovalAndRetriesValidation() (gas: 531558)\n[PASS] test_firstCredit_approvesOnce_andLaterCreditsStillWork() (gas: 397349)\n[PASS] test_firstCredit_revertsOnAssetMismatch() (gas: 791551)\n[PASS] test_integrator_tryCatchSurvivesPausedVault() (gas: 1053516)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 177.57ms (456.49ms CPU time)\n\nRan 10 tests for test/RegistryAuditRegression.t.sol:RegistryAuditRegressionTest\n[PASS] testFuzz_applicationPaysCurrentPrice(uint96) (runs: 256, μ: 2282333, ~: 2282180)\nLogs:\n  Bound result 159813184955\n\n[PASS] test_defendedChallengeFromAnotherWalletDoesNotRenewImmunity() (gas: 6666301)\n[PASS] test_defendedSelfChallengeDoesNotRenewImmunity() (gas: 15564501)\n[PASS] test_permissionlessApplicantCanOccupySlotUntilRejected() (gas: 4520315)\n[PASS] test_priceRiseAndFall_preserveBondAndExactPayment() (gas: 6856024)\n[PASS] test_retiredActionApplicationMovesNothing() (gas: 278791)\n[PASS] test_retiredActionRefusesBeforePaymentAndPreservesListing() (gas: 4667017)\n[PASS] test_signedAnswerMustReachItsOwnQuorum() (gas: 2375956)\n[PASS] test_stakingFaucetTokenCannotPayOracleFee() (gas: 3478238)\n[PASS] test_staleExactApprovalCannotSpendAnUnexpectedPriceIncrease() (gas: 342811)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 178.04ms (191.64ms CPU time)\n\nRan 19 tests for test/StackerEdges.t.sol:StackerEdgesTest\n[PASS] testFuzz_credit_pausedAlwaysRevertsAndMovesNothing(address,uint256) (runs: 1000, μ: 229767, ~: 229550)\nLogs:\n  Bound result 42000000000000000000\n\n[PASS] testFuzz_credit_repeatedCyclesExtractNoDust(uint256,uint8) (runs: 1000, μ: 1541346, ~: 1369861)\nLogs:\n  Bound result 1\n\n[PASS] testFuzz_credit_shortBalanceAlwaysReverts(uint256,uint256) (runs: 1000, μ: 388764, ~: 388707)\nLogs:\n  Bound result 274086487053717301105816\n  Bound result 2275131159327\n\n[PASS] testFuzz_credit_thenRedeem_noFreeProfit(uint256,uint256,uint256) (runs: 1000, μ: 740962, ~: 761716)\nLogs:\n  Bound result 4\n  Bound result 408409719601869714\n  Bound result 36698029357467554710\n\n[PASS] testFuzz_credit_traderValueWithinOneShareOfAmount(uint256,uint256,uint256) (runs: 1000, μ: 682330, ~: 688790)\nLogs:\n  Bound result 4\n  Bound result 408409719601869714\n  Bound result 36698029357467554710\n\n[PASS] testFuzz_credit_zeroSharesGuardTracksVaultPreview(uint256,uint256) (runs: 1000, μ: 492298, ~: 510495)\nLogs:\n  Bound result 249057\n  Bound result 371323325276670431\n\n[PASS] test_credit_allowanceConsumedExactly_secondCallReverts() (gas: 615593)\n[PASS] test_credit_astronomicalButRepresentable() (gas: 365161)\n[PASS] test_credit_balanceConsumedExactly_secondCallReverts() (gas: 591023)\n[PASS] test_credit_eventMatchesReturnAndBalanceDeltaAtNonUnitPrice() (gas: 662705)\n[PASS] test_credit_maxUint_revertsCleanlyInVaultMath() (gas: 238830)\n[PASS] test_credit_oneWei() (gas: 361738)\n[PASS] test_credit_pausedBeatsShortAllowance_nothingPulled() (gas: 468463)\n[PASS] test_credit_projectIsTrader_countedOnBothSides() (gas: 326667)\n[PASS] test_credit_reentrancyFromVaultIsBlocked() (gas: 736980)\n[PASS] test_credit_zeroAmountWhilePaused_returnsZeroWithoutTouchingVault() (gas: 91064)\n[PASS] test_credit_zeroTraderWhilePaused_stillZeroTrader() (gas: 89528)\n[PASS] test_credit_zeroTraderWithShortAllowance_stillZeroTrader() (gas: 285166)\n[PASS] test_strayImdInStacker_isNeverSpentByCredit() (gas: 522294)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 178.00ms (951.74ms CPU time)\n\nRan 1 test for test/StackerInvariant.t.sol:StackerInvariantTest\n[PASS]\nStackerInvariantTest invariants:\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_totalsConsistent\n[PASS] invariant_vaultConservation\n StackerInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭----------------+-------------+-------+---------+----------╮\n| Contract       | Selector    | Calls | Reverts | Discards |\n+===========================================================+\n| StackerHandler | advance     | 424   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | credit      | 398   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | donate      | 383   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | redeem      | 424   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | togglePause | 419   | 0       | 0        |\n╰----------------+-------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 8577\n  Bound result 5\n  Bound result 1000000\n  Bound result 3\n  Bound result 13245\n  Bound result 1800000000\n  Bound result 9325\n  Bound result 9\n  Bound result 5\n  Bound result 1\n  Bound result 10\n  Bound result 996943734943523862138974\n  Bound result 6509\n  Bound result 4\n  Bound result 680892552760744704908253\n  Bound result 10\n  Bound result 9\n  Bound result 8550\n  Bound result 2\n  Bound result 7\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 478.29ms (475.67ms CPU time)\n\nRan 2 tests for test/ProjectRegistryInvariant.t.sol:ProjectRegistryInvariantTest\n[PASS]\nProjectRegistryInvariantTest invariants:\n[PASS] invariant_holdsOnlyOpenBonds\n[PASS] invariant_listingCounts\n[PASS] invariant_recordsConsistent\n ProjectRegistryInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-----------------+-------------------+-------+---------+----------╮\n| Contract        | Selector          | Calls | Reverts | Discards |\n+==================================================================+\n| RegistryHandler | answer            | 265   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | applyFor          | 239   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | challengeFor      | 249   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | completeAndExpire | 258   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | expireStale       | 243   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | failFor           | 247   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | handOver          | 287   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | passTime          | 260   | 0       | 0        |\n╰-----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 80\n  Bound result 93\n  Bound result 30\n  Bound result 22128\n  Bound result 140004\n  Bound result 111162\n  Bound result 96216\n\n[PASS] test_handlerReachesEveryOutcome() (gas: 13759505)\nLogs:\n  Bound result 50\n  Bound result 25\n  Bound result 100\n  Bound result 172800\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 577.40ms (582.41ms CPU time)\n\nRan 2 tests for test/StackerInvariantExtended.t.sol:StackerInvariantExtendedTest\n[PASS]\nStackerInvariantExtendedTest invariants:\n[PASS] invariant_imdSupplyConservation\n[PASS] invariant_pauseAndOwnershipStateMachine\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_stackerTotals\n[PASS] invariant_vaultConservation\n[PASS] invariant_vaultSolvent\n StackerInvariantExtendedTest invariants (runs: 128, calls: 6144, reverts: 0)\n\n╭-----------------+----------------+-------+---------+----------╮\n| Contract        | Selector       | Calls | Reverts | Discards |\n+===============================================================+\n| ExtendedHandler | advance        | 485   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | credit         | 484   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | creditTiny     | 442   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | depositDirect  | 480   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | donate         | 482   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | faucet         | 480   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | redeem         | 447   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | renounce       | 490   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | rescue         | 454   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | setAllowance   | 427   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | togglePause    | 495   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | transferShares | 463   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | withdraw       | 515   | 0       | 0        |\n╰-----------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 11\n  Bound result 19527\n  Bound result 7893\n  Bound result 1928448829765391450633\n  Bound result 3\n  Bound result 2006\n  Bound result 10\n  Bound result 17980014954669111549343\n  Bound result 1\n  Bound result 10\n  Bound result 12359\n  Bound result 2220\n  Bound result 13239\n  Bound result 10\n  Bound result 32421\n  Bound result 126\n  Bound result 8\n  Bound result 1\n  Bound result 20483767913317336088880\n  Bound result 22444\n  Bound result 969529035837012967424\n  Bound result 1800003600\n  Bound result 10\n  Bound result 2000\n  Bound result 10\n  Bound result 1700000000\n  Bound result 729\n\n[PASS] test_handlerReachesEveryCreditOutcome() (gas: 4540137)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 5\n  Bound result 100000000000000000000\n  Bound result 1\n  Bound result 50000000000000000000\n  Bound result 7\n  Bound result 24000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 10000000000000000000\n  Bound result 1000000000000000000000\n  Bound result 372757101\n  Bound result 684498244\n  Bound result 1000000000000000000\n  Bound result 2949193105425070115\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 3.98s (3.98s CPU time)\n\nRan 18 test suites in 3.99s (5.93s CPU time): 94 tests passed, 0 failed, 7 skipped (101 total tests)\n","passed":true},{"durationMs":70,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ProjectRegistry.applyListing(address,string,string,uint16,address)\",\"ProjectRegistry.challenge(address,string)\",\"ProjectRegistry.expire(address)\",\"ProjectRegistry.onOracleFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"ProjectRegistry.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"ProjectRegistry.setBeneficiary(address,address)\",\"Stacker.credit(address,uint256)\"],\"files\":{\".github/ISSUE_TEMPLATE/listing-application.yml\":88,\".gitignore\":4,\"ADAPTATION.md\":65,\"NEXT_SESSION.md\":35,\"README.md\":227,\"docs/design.md\":295,\"docs/explainer.html\":247,\"docs/history.md\":89,\"docs/listing.md\":96,\"foundry.toml\":26,\"jobs/1-sepolia-launch.md\":23,\"jobs/2-sepolia-site.md\":18,\"jobs/3-list-plea.md\":21,\"jobs/4-mainnet-launch.md\":16,\"jobs/5-sepolia-v2-launch.md\":12,\"jobs/5-sepolia-v2-site.md\":10,\"jobs/requests/3-list-plea.json\":10,\"jobs/requests/4-mainnet-launch.json\":31,\"jobs/requests/5-sepolia-v2-launch-only.json\":31,\"jobs/requests/5-sepolia-v2-workflow.json\":50,\"launch.json\":25,\"listings/sepolia.json\":1,\"remappings.txt\":3,\"site/README.md\":57,\"site/app.mjs\":275,\"site/configure.mjs\":13,\"site/core.mjs\":221,\"site/index.html\":59,\"site/style.css\":1,\"site/test/app.test.mjs\":105,\"site/test/browser.mjs\":111,\"site/test/core.test.mjs\":115,\"site/test/fixture.mjs\":83,\"site/test/vendor/linkedom-0.18.12.mjs\":12761,\"site/test/vendor/linkedom-LICENSE\":15,\"site/vendor/ethers-6.17.0.mjs\":1,\"site/vendor/ethers-LICENSE.md\":21,\"src/ProjectRegistry.sol\":547,\"src/Stacker.sol\":98,\"src/oracle/OracleAttestation.sol\":265,\"test/Base.t.sol\":58,\"test/Deployment.t.sol\":99,\"test/FactoryRehearsal.t.sol\":47,\"test/MainnetFork.t.sol\":102,\"test/OracleConsumerConformance.t.sol\":140,\"test/ProjectRegistry.t.sol\":587,\"test/ProjectRegistryInvariant.t.sol\":233,\"test/RegistryAuditRegression.t.sol\":154,\"test/RegistryCallbackGas.t.sol\":111,\"test/RegistrySepoliaFork.t.sol\":111,\"test/SepoliaFork.t.sol\":88,\"test/Stacker.t.sol\":419,\"test/StackerEdges.t.sol\":390,\"test/StackerInvariant.t.sol\":148,\"test/StackerInvariantExtended.t.sol\":495,\"test/mocks/MockIntake.sol\":108,\"test/mocks/TestIMD.sol\":41,\"test/mocks/TestSIMD.sol\":178},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"807277430058ee0d47dd883ac6ff00d1384ce22311371899228de53c61fe1145","verifiedTreeHash":"257a7e6b4433d5760f0209a1c4164506ef130707","verifierVersion":"0.1.0+0e08a464"},{"checks":[{"durationMs":6611,"exitCode":0,"name":"build","output":"Compiling 72 files with Solc 0.8.26\nSolc 0.8.26 finished in 6.53s\nCompiler run successful!\n","passed":true},{"durationMs":3630,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RegistrySepoliaFork.t.sol:RegistrySepoliaForkTest\n[SKIP] test_sepolia_applyPaysTheRealIntake_thenAnswerLists() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 462.24µs (47.03µs CPU time)\n\nRan 3 tests for test/SepoliaFork.t.sol:SepoliaForkTest\n[SKIP] test_sepolia_creditEventAndTotals() (gas: 0)\n[SKIP] test_sepolia_liveFacts() (gas: 0)\n[SKIP] test_sepolia_pausedVaultRevertsThenRecovers() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 499.09µs (119.01µs CPU time)\n\nRan 3 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_fork_creditNewThenRepeatTrader() (gas: 0)\n[SKIP] test_fork_liveFacts() (gas: 0)\n[SKIP] test_fork_oneBlockHoldThenRedeem() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 625.66µs (168.14µs CPU time)\n\nRan 1 test for test/FactoryRehearsal.t.sol:FactoryRehearsalTest\n[PASS] test_sepoliaFactoryDeploysBothInOrderOnAnEmptyChain() (gas: 419482)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 558.81µs (465.57µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdListingTest\n[PASS] test_coldApplicationYes_deliveredWithin200k() (gas: 162651)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.66ms (331.06µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdRejectionTest\n[PASS] test_coldApplicationNo_deliveredWithin200k() (gas: 156293)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.65ms (243.65µs CPU time)\n\nRan 5 tests for test/OracleConsumerConformance.t.sol:OracleConsumerConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 181781)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3671)\n[PASS] test_digestMatchesTheProtocol() (gas: 13664)\n[PASS] test_protocolSignaturePassesVerificationBeforePanelPolicy() (gas: 69567)\n[PASS] test_tamperingTheProtocolVectorFailsSignatureVerification() (gas: 64591)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 2.38ms (1.16ms CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDefenseTest\n[PASS] test_coldDefendedChallenge_deliveredWithin200k() (gas: 190529)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.47ms (256.28µs CPU time)\n\nRan 2 tests for test/VaultTrustRegression.t.sol:VaultTrustRegressionTest\n[PASS] test_dustHoldThroughStackerAndDirectVault() (gas: 910410)\n[PASS] test_vaultOwnerCanSweepCashback() (gas: 637844)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.02ms (1.28ms CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDelistingTest\n[PASS] test_coldDelistedChallenge_deliveredWithin200k() (gas: 171535)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 4.24ms (354.52µs CPU time)\n\nRan 3 tests for test/RegistryCallbackGas.t.sol:RegistryColdFailureTest\n[PASS] test_coldChallengeAfterDeadline_canExpire() (gas: 128234)\n[PASS] test_coldDisagreedChallenge_deliveredWithin200k() (gas: 140182)\n[PASS] test_coldRefusedChallenge_deliveredWithin200k() (gas: 140266)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 4.98ms (411.89µs CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_emptyChainRehearsal_constructorPasses() (gas: 25809)\n[PASS] test_launchManifest_knownShape() (gas: 32434)\n[PASS] test_registry_emptyChainRehearsal_constructorPasses() (gas: 7587633)\n[PASS] test_runtimeSizeAndNoEscapeOpcodes() (gas: 4217889)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 113.99ms (22.74ms CPU time)\n\nRan 10 tests for test/RegistryAuditRegression.t.sol:RegistryAuditRegressionTest\n[PASS] testFuzz_applicationPaysCurrentPrice(uint96) (runs: 256, μ: 2282626, ~: 2282469)\nLogs:\n  Bound result 14291936599896774\n\n[PASS] test_defendedChallengeFromAnotherWalletDoesNotRenewImmunity() (gas: 6841925)\n[PASS] test_defendedSelfChallengeDoesNotRenewImmunity() (gas: 16118511)\n[PASS] test_permissionlessApplicantCanOccupySlotUntilRejected() (gas: 4563271)\n[PASS] test_priceRiseAndFall_preserveBondAndExactPayment() (gas: 7058072)\n[PASS] test_retiredActionApplicationMovesNothing() (gas: 279090)\n[PASS] test_retiredActionRefusesBeforePaymentAndPreservesListing() (gas: 4760949)\n[PASS] test_signedAnswerMustReachItsOwnQuorum() (gas: 2398027)\n[PASS] test_stakingFaucetTokenCannotPayOracleFee() (gas: 3500658)\n[PASS] test_staleExactApprovalCannotSpendAnUnexpectedPriceIncrease() (gas: 343121)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 158.10ms (182.82ms CPU time)\n\nRan 20 tests for test/Stacker.t.sol:StackerTest\n[PASS] testFuzz_credit(address,uint256) (runs: 256, μ: 387935, ~: 387760)\nLogs:\n  Bound result 578188637579558503091740\n\n[PASS] testFuzz_credit_shortAllowanceAlwaysReverts(uint256,uint256) (runs: 256, μ: 367052, ~: 368825)\nLogs:\n  Bound result 377945248399945\n  Bound result 316378394207657\n\n[PASS] testFuzz_credit_twoTradersProportional(uint256,uint256) (runs: 256, μ: 430143, ~: 430206)\nLogs:\n  Bound result 77000000000000000000\n  Bound result 100\n\n[PASS] test_constructor_doesNotCallExistingVaultOrToken() (gas: 56037)\n[PASS] test_constructor_vaultWithoutCode_creditCannotMove() (gas: 131214)\n[PASS] test_constructor_wiringWithoutExternalCalls() (gas: 43846)\n[PASS] test_credit_manyProjectsAndTraders() (gas: 9371828)\n[PASS] test_credit_revertsOnShortAllowance() (gas: 378414)\n[PASS] test_credit_revertsOnShortBalance() (gas: 370521)\n[PASS] test_credit_revertsOnZeroShares() (gas: 383268)\n[PASS] test_credit_revertsWhenVaultPaused() (gas: 508017)\n[PASS] test_credit_sharesFollowVaultPrice() (gas: 617727)\n[PASS] test_credit_sharesGoOnlyToTrader() (gas: 374387)\n[PASS] test_credit_totalsAndEvent() (gas: 493973)\n[PASS] test_credit_zeroAmountReturnsZeroNoEvent() (gas: 80024)\n[PASS] test_credit_zeroTraderReverts() (gas: 66272)\n[PASS] test_failedFirstCredit_rollsBackApprovalAndRetriesValidation() (gas: 531558)\n[PASS] test_firstCredit_approvesOnce_andLaterCreditsStillWork() (gas: 397349)\n[PASS] test_firstCredit_revertsOnAssetMismatch() (gas: 791551)\n[PASS] test_integrator_tryCatchSurvivesPausedVault() (gas: 1053516)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 202.10ms (447.08ms CPU time)\n\nRan 16 tests for test/RegistryRevisionRegression.t.sol:RegistryRevisionRegressionTest\n[PASS] testFuzz_answerIsConsumedAcrossApplications(bool) (runs: 256, μ: 6874321, ~: 6877494)\n[PASS] testFuzz_beneficiaryUnlocksAfterFailureOrExpiry(bool) (runs: 256, μ: 4670898, ~: 4677040)\n[PASS] testFuzz_challengeAllowsRateChangesWithinTheRules(uint16) (runs: 256, μ: 5437447, ~: 5437682)\nLogs:\n  Bound result 72\n\n[PASS] testFuzz_validCooldownCanList(uint64) (runs: 256, μ: 2416535, ~: 2416245)\nLogs:\n  Bound result 19839066\n\n[PASS] test_applicationAnswerCannotDefendAChallengeAndSpendItsBond() (gas: 4655586)\n[PASS] test_beneficiaryCannotTransferAfterChallengeDelists() (gas: 4655630)\n[PASS] test_challengeBodyLimitsAndConsumerDomain() (gas: 4987284)\n[PASS] test_constructorRefusesOverflowingAndExcessiveCooldowns() (gas: 16578)\n[PASS] test_invalidAnswerDoesNotConsumeUUID() (gas: 2477345)\n[PASS] test_legacyChallengeCannotChargeAfterAnyBeneficiaryHandoff() (gas: 9335977)\n[PASS] test_openChallengeLocksBeneficiaryAndDefendedBondDestination() (gas: 4992489)\n[PASS] test_pinnedChallengePreservesCooldownAndSlotRules() (gas: 4768551)\n[PASS] test_pinnedChallengeRefusesFrontrunBeforeAnyPayment() (gas: 5090415)\n[PASS] test_selfChallengeOccupiesSlotOnlyUntilItSettles() (gas: 6879117)\n[PASS] test_settingSameBeneficiaryDoesNotDisableLegacyChallenge() (gas: 4670015)\n[PASS] test_zeroAndMaximumCooldownCanList() (gas: 4743487)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 219.59ms (786.30ms CPU time)\n\nRan 23 tests for test/ProjectRegistry.t.sol:ProjectRegistryTest\n[PASS] testFuzz_apply_nameIsSafeOrRefused(bytes) (runs: 256, μ: 255857, ~: 55509)\n[PASS] testFuzz_apply_rate(uint16) (runs: 256, μ: 272459, ~: 47467)\n[PASS] test_answer_freshnessAndPanelChecks() (gas: 2707488)\n[PASS] test_answer_mustBeSignedByTheOracleForThisContract() (gas: 2396222)\n[PASS] test_answer_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2405976)\n[PASS] test_apply_bodyIsTheOracleBody() (gas: 2401501)\n[PASS] test_apply_oneOpenQuestionAtATime_andNotWhenListed() (gas: 2403016)\n[PASS] test_apply_paysExactlyTheFeeAndAsks() (gas: 2293926)\n[PASS] test_apply_validation() (gas: 562562)\n[PASS] test_callbackOutOfGas_isRecoverableThroughExpire() (gas: 4415041)\n[PASS] test_challenge_defended_bondToBeneficiary_noNewCooldown() (gas: 4715447)\n[PASS] test_challenge_failureOrExpiry_returnsTheBond_projectStaysListed() (gas: 6892809)\n[PASS] test_challenge_lost_delistsFromThisBlock_bondBack() (gas: 6868886)\n[PASS] test_challenge_onlyListed_afterCooldown_oneAtATime() (gas: 4667316)\n[PASS] test_challenge_paysFeeAndBond_bodyNamesTheReason() (gas: 4741766)\n[PASS] test_constructor_rejectsZeroAddresses() (gas: 6519)\n[PASS] test_constructor_wiring() (gas: 74024)\n[PASS] test_expire_afterADay_orWhenTheIntakeCompletedWithoutAnAnswer() (gas: 4468682)\n[PASS] test_failure_clearsTheApplication_andNeverLists() (gas: 4342853)\n[PASS] test_failure_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2234015)\n[PASS] test_no_rejects_andTheProjectCanApplyAgain() (gas: 4524496)\n[PASS] test_setBeneficiary_onlyTheBeneficiaryOfAListedProject() (gas: 2472906)\n[PASS] test_yes_listsFromThisBlock() (gas: 2336847)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 219.61ms (449.37ms CPU time)\n\nRan 19 tests for test/StackerEdges.t.sol:StackerEdgesTest\n[PASS] testFuzz_credit_pausedAlwaysRevertsAndMovesNothing(address,uint256) (runs: 1000, μ: 229773, ~: 229550)\nLogs:\n  Bound result 288158575792322907279151\n\n[PASS] testFuzz_credit_repeatedCyclesExtractNoDust(uint256,uint8) (runs: 1000, μ: 1556751, ~: 1369873)\nLogs:\n  Bound result 11\n\n[PASS] testFuzz_credit_shortBalanceAlwaysReverts(uint256,uint256) (runs: 1000, μ: 388755, ~: 388695)\nLogs:\n  Bound result 122\n  Bound result 64\n\n[PASS] testFuzz_credit_thenRedeem_noFreeProfit(uint256,uint256,uint256) (runs: 1000, μ: 738267, ~: 761716)\nLogs:\n  Bound result 78\n  Bound result 92376271269758018030951\n  Bound result 99999999999999999999999\n\n[PASS] testFuzz_credit_traderValueWithinOneShareOfAmount(uint256,uint256,uint256) (runs: 1000, μ: 681901, ~: 688802)\nLogs:\n  Bound result 1358\n  Bound result 127\n  Bound result 20220\n\n[PASS] testFuzz_credit_zeroSharesGuardTracksVaultPreview(uint256,uint256) (runs: 1000, μ: 489860, ~: 510495)\nLogs:\n  Bound result 614419376812182153\n  Bound result 715243605018829054\n\n[PASS] test_credit_allowanceConsumedExactly_secondCallReverts() (gas: 615593)\n[PASS] test_credit_astronomicalButRepresentable() (gas: 365161)\n[PASS] test_credit_balanceConsumedExactly_secondCallReverts() (gas: 591023)\n[PASS] test_credit_eventMatchesReturnAndBalanceDeltaAtNonUnitPrice() (gas: 662705)\n[PASS] test_credit_maxUint_revertsCleanlyInVaultMath() (gas: 238830)\n[PASS] test_credit_oneWei() (gas: 361738)\n[PASS] test_credit_pausedBeatsShortAllowance_nothingPulled() (gas: 468463)\n[PASS] test_credit_projectIsTrader_countedOnBothSides() (gas: 326667)\n[PASS] test_credit_reentrancyFromVaultIsBlocked() (gas: 736980)\n[PASS] test_credit_zeroAmountWhilePaused_returnsZeroWithoutTouchingVault() (gas: 91064)\n[PASS] test_credit_zeroTraderWhilePaused_stillZeroTrader() (gas: 89528)\n[PASS] test_credit_zeroTraderWithShortAllowance_stillZeroTrader() (gas: 285166)\n[PASS] test_strayImdInStacker_isNeverSpentByCredit() (gas: 522294)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 219.61ms (1.21s CPU time)\n\nRan 1 test for test/StackerInvariant.t.sol:StackerInvariantTest\n[PASS]\nStackerInvariantTest invariants:\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_totalsConsistent\n[PASS] invariant_vaultConservation\n StackerInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭----------------+-------------+-------+---------+----------╮\n| Contract       | Selector    | Calls | Reverts | Discards |\n+===========================================================+\n| StackerHandler | advance     | 400   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | credit      | 401   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | donate      | 409   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | redeem      | 408   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | togglePause | 430   | 0       | 0        |\n╰----------------+-------------+-------+---------+----------╯\n\nLogs:\n  Bound result 694430144287860247502113\n  Bound result 905318062732978912962048\n  Bound result 10\n  Bound result 5\n  Bound result 165992964466540702839773\n  Bound result 9\n  Bound result 2\n  Bound result 7\n  Bound result 754526290098847999273\n  Bound result 50000000000000000000\n  Bound result 4203839940603766843\n  Bound result 6\n  Bound result 125851850757528677285397\n  Bound result 541169514875756493851\n  Bound result 1266\n  Bound result 5\n  Bound result 9\n  Bound result 475620823957704031918423\n  Bound result 10\n  Bound result 10\n  Bound result 6\n  Bound result 304\n  Bound result 11587\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 526.28ms (522.62ms CPU time)\n\nRan 2 tests for test/ProjectRegistryInvariant.t.sol:ProjectRegistryInvariantTest\n[PASS]\nProjectRegistryInvariantTest invariants:\n[PASS] invariant_holdsOnlyOpenBonds\n[PASS] invariant_listingCounts\n[PASS] invariant_recordsConsistent\n ProjectRegistryInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-----------------+-------------------+-------+---------+----------╮\n| Contract        | Selector          | Calls | Reverts | Discards |\n+==================================================================+\n| RegistryHandler | answer            | 224   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | applyFor          | 262   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | challengeFor      | 274   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | completeAndExpire | 252   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | expireStale       | 265   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | failFor           | 255   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | handOver          | 257   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | passTime          | 259   | 0       | 0        |\n╰-----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 71\n  Bound result 95\n  Bound result 112009\n  Bound result 73\n  Bound result 160000\n  Bound result 4280\n  Bound result 86\n  Bound result 3600\n\n[PASS] test_handlerReachesEveryOutcome() (gas: 14028842)\nLogs:\n  Bound result 50\n  Bound result 25\n  Bound result 100\n  Bound result 172800\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 542.75ms (547.02ms CPU time)\n\nRan 2 tests for test/StackerInvariantExtended.t.sol:StackerInvariantExtendedTest\n[PASS]\nStackerInvariantExtendedTest invariants:\n[PASS] invariant_imdSupplyConservation\n[PASS] invariant_pauseAndOwnershipStateMachine\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_stackerTotals\n[PASS] invariant_vaultConservation\n[PASS] invariant_vaultSolvent\n StackerInvariantExtendedTest invariants (runs: 128, calls: 6144, reverts: 0)\n\n╭-----------------+----------------+-------+---------+----------╮\n| Contract        | Selector       | Calls | Reverts | Discards |\n+===============================================================+\n| ExtendedHandler | advance        | 490   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | credit         | 474   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | creditTiny     | 434   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | depositDirect  | 455   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | donate         | 458   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | faucet         | 488   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | redeem         | 472   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | renounce       | 511   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | rescue         | 459   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | setAllowance   | 475   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | togglePause    | 464   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | transferShares | 506   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | withdraw       | 458   | 0       | 0        |\n╰-----------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 7000000000000000000\n  Bound result 6\n  Bound result 5000000000000000000000\n  Bound result 1826008360574375033935\n  Bound result 8965881843675374547202\n  Bound result 200\n  Bound result 2211\n  Bound result 6\n  Bound result 4\n  Bound result 15189\n  Bound result 17346\n  Bound result 1000000\n  Bound result 1259785\n  Bound result 32\n  Bound result 24\n  Bound result 10000000000000000000\n  Bound result 9405\n  Bound result 1000000\n  Bound result 2870408174833857\n  Bound result 5\n  Bound result 5\n  Bound result 17995\n  Bound result 360\n  Bound result 6\n  Bound result 1029\n  Bound result 9928461891782872549115\n\n[PASS] test_handlerReachesEveryCreditOutcome() (gas: 4540137)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 5\n  Bound result 100000000000000000000\n  Bound result 1\n  Bound result 50000000000000000000\n  Bound result 7\n  Bound result 24000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 10000000000000000000\n  Bound result 1000000000000000000000\n  Bound result 372757101\n  Bound result 684498244\n  Bound result 1000000000000000000\n  Bound result 2949193105425070115\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 3.54s (3.53s CPU time)\n\nRan 20 test suites in 3.54s (5.76s CPU time): 112 tests passed, 0 failed, 7 skipped (119 total tests)\n","passed":true},{"durationMs":59,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ProjectRegistry.applyListing(address,string,string,uint16,address)\",\"ProjectRegistry.challenge(address,string)\",\"ProjectRegistry.challengeForBeneficiary(address,string,address)\",\"ProjectRegistry.expire(address)\",\"ProjectRegistry.onOracleFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"ProjectRegistry.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"ProjectRegistry.setBeneficiary(address,address)\",\"Stacker.credit(address,uint256)\"],\"files\":{\".github/ISSUE_TEMPLATE/listing-application.yml\":88,\".gitignore\":4,\"ADAPTATION.md\":99,\"NEXT_SESSION.md\":35,\"README.md\":227,\"docs/design.md\":299,\"docs/explainer.html\":247,\"docs/history.md\":89,\"docs/listing.md\":96,\"foundry.toml\":26,\"jobs/1-sepolia-launch.md\":23,\"jobs/2-sepolia-site.md\":18,\"jobs/3-list-plea.md\":21,\"jobs/4-mainnet-launch.md\":16,\"jobs/5-sepolia-v2-launch.md\":12,\"jobs/5-sepolia-v2-site.md\":10,\"jobs/requests/3-list-plea.json\":10,\"jobs/requests/4-mainnet-launch.json\":31,\"jobs/requests/5-sepolia-v2-launch-only.json\":31,\"jobs/requests/5-sepolia-v2-workflow.json\":50,\"launch.json\":25,\"listings/sepolia.json\":1,\"remappings.txt\":3,\"site/README.md\":63,\"site/app.mjs\":280,\"site/configure.mjs\":13,\"site/core.mjs\":222,\"site/index.html\":61,\"site/style.css\":1,\"site/test/app.test.mjs\":142,\"site/test/browser.mjs\":111,\"site/test/core.test.mjs\":115,\"site/test/fixture.mjs\":97,\"site/test/vendor/linkedom-0.18.12.mjs\":12761,\"site/test/vendor/linkedom-LICENSE\":15,\"site/vendor/ethers-6.17.0.mjs\":1,\"site/vendor/ethers-LICENSE.md\":21,\"src/ProjectRegistry.sol\":607,\"src/Stacker.sol\":98,\"src/oracle/OracleAttestation.sol\":265,\"test/Base.t.sol\":58,\"test/Deployment.t.sol\":99,\"test/FactoryRehearsal.t.sol\":47,\"test/MainnetFork.t.sol\":102,\"test/OracleConsumerConformance.t.sol\":140,\"test/ProjectRegistry.t.sol\":587,\"test/ProjectRegistryInvariant.t.sol\":233,\"test/RegistryAuditRegression.t.sol\":157,\"test/RegistryCallbackGas.t.sol\":111,\"test/RegistryRevisionRegression.t.sol\":325,\"test/RegistrySepoliaFork.t.sol\":111,\"test/SepoliaFork.t.sol\":88,\"test/Stacker.t.sol\":419,\"test/StackerEdges.t.sol\":390,\"test/StackerInvariant.t.sol\":148,\"test/StackerInvariantExtended.t.sol\":495,\"test/VaultTrustRegression.t.sol\":41,\"test/mocks/MockIntake.sol\":108,\"test/mocks/TestIMD.sol\":41,\"test/mocks/TestSIMD.sol\":178},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"8e60751ee6a5d7d0ed8d3e88781d70e71bc7052f7ee2c64a1b393241d0d1f000","verifiedTreeHash":"ebf090ee4b7e1d19beeb51ed26a7ea87e3a1413f","verifierVersion":"0.1.0+0e08a464"},{"checks":[{"durationMs":8753,"exitCode":0,"name":"build","output":"Compiling 76 files with Solc 0.8.26\nSolc 0.8.26 finished in 8.65s\nCompiler run successful!\n","passed":true},{"durationMs":5025,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RegistrySepoliaFork.t.sol:RegistrySepoliaForkTest\n[SKIP] test_sepolia_applyPaysTheRealIntake_thenAnswerLists() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 418.03µs (40.48µs CPU time)\n\nRan 3 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_fork_creditNewThenRepeatTrader() (gas: 0)\n[SKIP] test_fork_liveFacts() (gas: 0)\n[SKIP] test_fork_oneBlockHoldThenRedeem() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 784.26µs (287.75µs CPU time)\n\nRan 3 tests for test/SepoliaFork.t.sol:SepoliaForkTest\n[SKIP] test_sepolia_creditEventAndTotals() (gas: 0)\n[SKIP] test_sepolia_liveFacts() (gas: 0)\n[SKIP] test_sepolia_pausedVaultRevertsThenRecovers() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 3 skipped; finished in 851.48µs (40.07µs CPU time)\n\nRan 1 test for test/FactoryRehearsal.t.sol:FactoryRehearsalTest\n[PASS] test_sepoliaFactoryDeploysBothInOrderOnAnEmptyChain() (gas: 419482)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 873.00µs (737.83µs CPU time)\n\nRan 2 tests for test/VaultTrustRegression.t.sol:VaultTrustRegressionTest\n[PASS] test_dustHoldThroughStackerAndDirectVault() (gas: 910410)\n[PASS] test_vaultOwnerCanSweepCashback() (gas: 637844)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 2.02ms (2.56ms CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdRejectionTest\n[PASS] test_coldApplicationNo_deliveredWithin200k() (gas: 156293)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.37ms (212.45µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdListingTest\n[PASS] test_coldApplicationYes_deliveredWithin200k() (gas: 162651)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.54ms (264.93µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDefenseTest\n[PASS] test_coldDefendedChallenge_deliveredWithin200k() (gas: 190529)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.59ms (167.43µs CPU time)\n\nRan 1 test for test/RegistryCallbackGas.t.sol:RegistryColdDelistingTest\n[PASS] test_coldDelistedChallenge_deliveredWithin200k() (gas: 171535)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.31ms (260.10µs CPU time)\n\nRan 3 tests for test/RegistryCallbackGas.t.sol:RegistryColdFailureTest\n[PASS] test_coldChallengeAfterDeadline_canExpire() (gas: 128234)\n[PASS] test_coldDisagreedChallenge_deliveredWithin200k() (gas: 140182)\n[PASS] test_coldRefusedChallenge_deliveredWithin200k() (gas: 140266)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 3.75ms (269.13µs CPU time)\n\nRan 5 tests for test/OracleConsumerConformance.t.sol:OracleConsumerConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 181781)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3671)\n[PASS] test_digestMatchesTheProtocol() (gas: 13664)\n[PASS] test_protocolSignaturePassesVerificationBeforePanelPolicy() (gas: 69567)\n[PASS] test_tamperingTheProtocolVectorFailsSignatureVerification() (gas: 64591)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 4.05ms (1.11ms CPU time)\n\nRan 10 tests for test/RegistryAuditRegression.t.sol:RegistryAuditRegressionTest\n[PASS] testFuzz_applicationPaysCurrentPrice(uint96) (runs: 256, μ: 2282667, ~: 2282481)\nLogs:\n  Bound result 91564907701381788882\n\n[PASS] test_defendedChallengeFromAnotherWalletDoesNotRenewImmunity() (gas: 6841925)\n[PASS] test_defendedSelfChallengeDoesNotRenewImmunity() (gas: 16118511)\n[PASS] test_permissionlessApplicantCanOccupySlotUntilRejected() (gas: 4563271)\n[PASS] test_priceRiseAndFall_preserveBondAndExactPayment() (gas: 7058072)\n[PASS] test_retiredActionApplicationMovesNothing() (gas: 279090)\n[PASS] test_retiredActionRefusesBeforePaymentAndPreservesListing() (gas: 4760949)\n[PASS] test_signedAnswerMustReachItsOwnQuorum() (gas: 2398027)\n[PASS] test_stakingFaucetTokenCannotPayOracleFee() (gas: 3500658)\n[PASS] test_staleExactApprovalCannotSpendAnUnexpectedPriceIncrease() (gas: 343121)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 144.21ms (153.47ms CPU time)\n\nRan 20 tests for test/Stacker.t.sol:StackerTest\n[PASS] testFuzz_credit(address,uint256) (runs: 256, μ: 387999, ~: 387772)\nLogs:\n  Bound result 220979053115539385734852\n\n[PASS] testFuzz_credit_shortAllowanceAlwaysReverts(uint256,uint256) (runs: 256, μ: 367793, ~: 368801)\nLogs:\n  Bound result 87535255225711187620\n  Bound result 76156556738009673004\n\n[PASS] testFuzz_credit_twoTradersProportional(uint256,uint256) (runs: 256, μ: 430126, ~: 430194)\nLogs:\n  Bound result 156621390692699925071084\n  Bound result 87535255225711187620\n\n[PASS] test_constructor_doesNotCallExistingVaultOrToken() (gas: 56037)\n[PASS] test_constructor_vaultWithoutCode_creditCannotMove() (gas: 131214)\n[PASS] test_constructor_wiringWithoutExternalCalls() (gas: 43846)\n[PASS] test_credit_manyProjectsAndTraders() (gas: 9371828)\n[PASS] test_credit_revertsOnShortAllowance() (gas: 378414)\n[PASS] test_credit_revertsOnShortBalance() (gas: 370521)\n[PASS] test_credit_revertsOnZeroShares() (gas: 383268)\n[PASS] test_credit_revertsWhenVaultPaused() (gas: 508017)\n[PASS] test_credit_sharesFollowVaultPrice() (gas: 617727)\n[PASS] test_credit_sharesGoOnlyToTrader() (gas: 374387)\n[PASS] test_credit_totalsAndEvent() (gas: 493973)\n[PASS] test_credit_zeroAmountReturnsZeroNoEvent() (gas: 80024)\n[PASS] test_credit_zeroTraderReverts() (gas: 66272)\n[PASS] test_failedFirstCredit_rollsBackApprovalAndRetriesValidation() (gas: 531558)\n[PASS] test_firstCredit_approvesOnce_andLaterCreditsStillWork() (gas: 397349)\n[PASS] test_firstCredit_revertsOnAssetMismatch() (gas: 791551)\n[PASS] test_integrator_tryCatchSurvivesPausedVault() (gas: 1053516)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 528.03ms (180.19ms CPU time)\n\nRan 7 tests for test/StackerExternalCalls.t.sol:StackerExternalCallsTest\n[PASS] testFuzz_creditMatchesDirectDepositFromSameVaultState(uint96,uint96,uint96) (runs: 1000, μ: 976803, ~: 976766)\nLogs:\n  Bound result 210802509515751954171\n  Bound result 750001657817416\n  Bound result 1868965089316\n\n[PASS] testFuzz_lateFailureRollsBackAllEffects(uint96,bool,bool) (runs: 1000, μ: 2935580, ~: 2941029)\nLogs:\n  Bound result 1\n\n[PASS] test_anotherCallersApprovalCannotBeSpent() (gas: 598484)\n[PASS] test_noReturnTokenStillMovesExactAssetsAndShares() (gas: 3117568)\n[PASS] test_oneWeiLateRevertRollsBackFirstApproval() (gas: 2937399)\n[PASS] test_tokenReentryDuringApprovalAndPullCannotCreateExtraCashback() (gas: 3738536)\n[PASS] test_zeroShareReturnRollsBackAnActualMint() (gas: 2925677)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 551.15ms (1.01s CPU time)\n\nRan 1 test for test/StackerInvariant.t.sol:StackerInvariantTest\n[PASS]\nStackerInvariantTest invariants:\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_totalsConsistent\n[PASS] invariant_vaultConservation\n StackerInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭----------------+-------------+-------+---------+----------╮\n| Contract       | Selector    | Calls | Reverts | Discards |\n+===========================================================+\n| StackerHandler | advance     | 397   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | credit      | 427   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | donate      | 425   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | redeem      | 390   | 0       | 0        |\n|----------------+-------------+-------+---------+----------|\n| StackerHandler | togglePause | 409   | 0       | 0        |\n╰----------------+-------------+-------+---------+----------╯\n\nLogs:\n  Bound result 2\n  Bound result 10000000000000000002\n  Bound result 2413\n  Bound result 969639840\n  Bound result 18446744073709551615\n  Bound result 4781\n  Bound result 6941\n  Bound result 2984\n  Bound result 13890\n  Bound result 1800000000\n  Bound result 231728193094346660384946\n  Bound result 999999999999999999991\n  Bound result 9627\n  Bound result 2\n  Bound result 65\n  Bound result 1000000000000000000000\n  Bound result 3\n  Bound result 7926\n  Bound result 1196832344\n  Bound result 65133314\n  Bound result 797527228365366118357567\n  Bound result 25\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 554.86ms (551.66ms CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_emptyChainRehearsal_constructorPasses() (gas: 25809)\n[PASS] test_launchManifest_knownShape() (gas: 31169)\n[PASS] test_registry_emptyChainRehearsal_constructorPasses() (gas: 7587633)\n[PASS] test_runtimeSizeAndNoEscapeOpcodes() (gas: 4217889)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 554.89ms (33.80ms CPU time)\n\nRan 16 tests for test/RegistryRevisionRegression.t.sol:RegistryRevisionRegressionTest\n[PASS] testFuzz_answerIsConsumedAcrossApplications(bool) (runs: 256, μ: 6874721, ~: 6877494)\n[PASS] testFuzz_beneficiaryUnlocksAfterFailureOrExpiry(bool) (runs: 256, μ: 4671672, ~: 4677040)\n[PASS] testFuzz_challengeAllowsRateChangesWithinTheRules(uint16) (runs: 256, μ: 5437520, ~: 5437682)\nLogs:\n  Bound result 81\n\n[PASS] testFuzz_validCooldownCanList(uint64) (runs: 256, μ: 2416535, ~: 2416245)\nLogs:\n  Bound result 24491340\n\n[PASS] test_applicationAnswerCannotDefendAChallengeAndSpendItsBond() (gas: 4655586)\n[PASS] test_beneficiaryCannotTransferAfterChallengeDelists() (gas: 4655630)\n[PASS] test_challengeBodyLimitsAndConsumerDomain() (gas: 4987284)\n[PASS] test_constructorRefusesOverflowingAndExcessiveCooldowns() (gas: 16578)\n[PASS] test_invalidAnswerDoesNotConsumeUUID() (gas: 2477345)\n[PASS] test_legacyChallengeCannotChargeAfterAnyBeneficiaryHandoff() (gas: 9335977)\n[PASS] test_openChallengeLocksBeneficiaryAndDefendedBondDestination() (gas: 4992489)\n[PASS] test_pinnedChallengePreservesCooldownAndSlotRules() (gas: 4768551)\n[PASS] test_pinnedChallengeRefusesFrontrunBeforeAnyPayment() (gas: 5090415)\n[PASS] test_selfChallengeOccupiesSlotOnlyUntilItSettles() (gas: 6879117)\n[PASS] test_settingSameBeneficiaryDoesNotDisableLegacyChallenge() (gas: 4670015)\n[PASS] test_zeroAndMaximumCooldownCanList() (gas: 4743487)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 555.02ms (1.05s CPU time)\n\nRan 8 tests for test/RegistryBodyProperties.t.sol:RegistryBodyPropertiesTest\n[PASS] testFuzz_applicationBodyRoundTripsValidText(bytes32,uint8,uint8,uint16) (runs: 1000, μ: 2688873, ~: 2650877)\nLogs:\n  Bound result 40\n  Bound result 61\n  Bound result 25\n\n[PASS] testFuzz_challengeBodyRoundTripsValidText(bytes32,uint16) (runs: 1000, μ: 5034998, ~: 4969702)\nLogs:\n  Bound result 13\n\n[PASS] test_applicationMaximumTextAndRate() (gas: 2929360)\n[PASS] test_applicationMinimumTextAndRate() (gas: 2572132)\n[PASS] test_challengeMaximumReason() (gas: 5362278)\n[PASS] test_challengeMinimumReason() (gas: 4887808)\n[PASS] test_everyForbiddenByteIsRejectedInEveryUserTextFieldBeforePayment() (gas: 52844082)\n[PASS] test_textLengthsJustOutsideLimitsAreAtomic() (gas: 2925383)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 571.02ms (926.84ms CPU time)\n\nRan 20 tests for test/RegistryAdversarial.t.sol:RegistryAdversarialTest\n[PASS] testFuzz_nonCanonicalBoolCannotDelist(uint256) (runs: 1000, μ: 4907848, ~: 4907804)\nLogs:\n  Bound result 6000000000000000000\n\n[PASS] testFuzz_oldCallbacksCannotCloseReplacementApplication(uint8) (runs: 1000, μ: 4992983, ~: 4999576)\nLogs:\n  Bound result 1\n\n[PASS] testFuzz_pendingDeadlineStillAllowsAnswerButNotExpiry(bool,bool) (runs: 1000, μ: 3760685, ~: 2611089)\n[PASS] testFuzz_shortBoolEncodingCannotReleaseBond(uint8) (runs: 1000, μ: 4786773, ~: 4786528)\nLogs:\n  Bound result 5\n\n[PASS] test_answerBeforeAskToleranceHasExactBoundary() (gas: 2591402)\n[PASS] test_attestationExpiryIsInclusive() (gas: 2581861)\n[PASS] test_beneficiaryHandoverWaitsForSettlementAndRevokesOldWallet() (gas: 7339024)\n[PASS] test_challengeCooldownHasExactBoundary() (gas: 4766568)\n[PASS] test_challengeShortAllowanceCannotBorrowDonatedFunds() (gas: 2767401)\n[PASS] test_emptyAndMalformedSignaturesCannotSettle() (gas: 3367805)\n[PASS] test_everySignedFieldIsAuthenticatedBeforeABondCanMove() (gas: 8968619)\n[PASS] test_futureIssuedAtToleranceHasExactBoundary() (gas: 2582150)\n[PASS] test_intakeRevertRollsBackFeeBondApprovalAndOpenRecord() (gas: 5037943)\n[PASS] test_maximumFeeAdditionRevertsWithoutChangingListing() (gas: 2704005)\n[PASS] test_oldChallengeCannotRefundTwiceOrCloseNewChallenge() (gas: 7486415)\n[PASS] test_oneSecondAfterDeadlineCannotReleaseBondToBeneficiary() (gas: 4914512)\n[PASS] test_signatureForSameAddressOnAnotherChainCannotReleaseBond() (gas: 4928419)\n[PASS] test_starvedChallengeCallbackRefundsOnlyChallenger() (gas: 4911522)\n[PASS] test_thirdPartyPaidQuestionCannotListOurProject() (gas: 2803516)\n[PASS] test_tokenReturningFalseCannotCreatePaidRequest() (gas: 2711822)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 573.90ms (1.79s CPU time)\n\nRan 23 tests for test/ProjectRegistry.t.sol:ProjectRegistryTest\n[PASS] testFuzz_apply_nameIsSafeOrRefused(bytes) (runs: 256, μ: 165043, ~: 55456)\n[PASS] testFuzz_apply_rate(uint16) (runs: 256, μ: 264126, ~: 47467)\n[PASS] test_answer_freshnessAndPanelChecks() (gas: 2707488)\n[PASS] test_answer_mustBeSignedByTheOracleForThisContract() (gas: 2396222)\n[PASS] test_answer_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2405976)\n[PASS] test_apply_bodyIsTheOracleBody() (gas: 2401501)\n[PASS] test_apply_oneOpenQuestionAtATime_andNotWhenListed() (gas: 2403016)\n[PASS] test_apply_paysExactlyTheFeeAndAsks() (gas: 2293926)\n[PASS] test_apply_validation() (gas: 562562)\n[PASS] test_callbackOutOfGas_isRecoverableThroughExpire() (gas: 4415041)\n[PASS] test_challenge_defended_bondToBeneficiary_noNewCooldown() (gas: 4715447)\n[PASS] test_challenge_failureOrExpiry_returnsTheBond_projectStaysListed() (gas: 6892809)\n[PASS] test_challenge_lost_delistsFromThisBlock_bondBack() (gas: 6868886)\n[PASS] test_challenge_onlyListed_afterCooldown_oneAtATime() (gas: 4667316)\n[PASS] test_challenge_paysFeeAndBond_bodyNamesTheReason() (gas: 4741766)\n[PASS] test_constructor_rejectsZeroAddresses() (gas: 6519)\n[PASS] test_constructor_wiring() (gas: 74024)\n[PASS] test_expire_afterADay_orWhenTheIntakeCompletedWithoutAnAnswer() (gas: 4468682)\n[PASS] test_failure_clearsTheApplication_andNeverLists() (gas: 4342853)\n[PASS] test_failure_onlyFromTheIntake_onlyForOurOpenRequest() (gas: 2234015)\n[PASS] test_no_rejects_andTheProjectCanApplyAgain() (gas: 4524496)\n[PASS] test_setBeneficiary_onlyTheBeneficiaryOfAListedProject() (gas: 2472906)\n[PASS] test_yes_listsFromThisBlock() (gas: 2336847)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 573.61ms (611.25ms CPU time)\n\nRan 19 tests for test/StackerEdges.t.sol:StackerEdgesTest\n[PASS] testFuzz_credit_pausedAlwaysRevertsAndMovesNothing(address,uint256) (runs: 1000, μ: 229796, ~: 229562)\nLogs:\n  Bound result 66542200291733835241494\n\n[PASS] testFuzz_credit_repeatedCyclesExtractNoDust(uint256,uint8) (runs: 1000, μ: 1576953, ~: 1369885)\nLogs:\n  Bound result 1\n\n[PASS] testFuzz_credit_shortBalanceAlwaysReverts(uint256,uint256) (runs: 1000, μ: 388731, ~: 388695)\nLogs:\n  Bound result 500000000000000000000000\n  Bound result 33381\n\n[PASS] testFuzz_credit_thenRedeem_noFreeProfit(uint256,uint256,uint256) (runs: 1000, μ: 741179, ~: 761716)\nLogs:\n  Bound result 266810332940144061988\n  Bound result 72767360962219781701484\n  Bound result 20828\n\n[PASS] testFuzz_credit_traderValueWithinOneShareOfAmount(uint256,uint256,uint256) (runs: 1000, μ: 682572, ~: 688802)\nLogs:\n  Bound result 80377271268921988447768\n  Bound result 2\n  Bound result 19782071352998135376886\n\n[PASS] testFuzz_credit_zeroSharesGuardTracksVaultPreview(uint256,uint256) (runs: 1000, μ: 492355, ~: 510483)\nLogs:\n  Bound result 2644001304362566941\n  Bound result 516360121085884656\n\n[PASS] test_credit_allowanceConsumedExactly_secondCallReverts() (gas: 615593)\n[PASS] test_credit_astronomicalButRepresentable() (gas: 365161)\n[PASS] test_credit_balanceConsumedExactly_secondCallReverts() (gas: 591023)\n[PASS] test_credit_eventMatchesReturnAndBalanceDeltaAtNonUnitPrice() (gas: 662705)\n[PASS] test_credit_maxUint_revertsCleanlyInVaultMath() (gas: 238830)\n[PASS] test_credit_oneWei() (gas: 361738)\n[PASS] test_credit_pausedBeatsShortAllowance_nothingPulled() (gas: 468463)\n[PASS] test_credit_projectIsTrader_countedOnBothSides() (gas: 326667)\n[PASS] test_credit_reentrancyFromVaultIsBlocked() (gas: 736980)\n[PASS] test_credit_zeroAmountWhilePaused_returnsZeroWithoutTouchingVault() (gas: 91064)\n[PASS] test_credit_zeroTraderWhilePaused_stillZeroTrader() (gas: 89528)\n[PASS] test_credit_zeroTraderWithShortAllowance_stillZeroTrader() (gas: 285166)\n[PASS] test_strayImdInStacker_isNeverSpentByCredit() (gas: 522294)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 574.26ms (3.19s CPU time)\n\nRan 2 tests for test/ProjectRegistryInvariant.t.sol:ProjectRegistryInvariantTest\n[PASS]\nProjectRegistryInvariantTest invariants:\n[PASS] invariant_holdsOnlyOpenBonds\n[PASS] invariant_listingCounts\n[PASS] invariant_recordsConsistent\n ProjectRegistryInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-----------------+-------------------+-------+---------+----------╮\n| Contract        | Selector          | Calls | Reverts | Discards |\n+==================================================================+\n| RegistryHandler | answer            | 267   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | applyFor          | 246   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | challengeFor      | 252   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | completeAndExpire | 287   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | expireStale       | 257   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | failFor           | 247   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | handOver          | 265   | 0       | 0        |\n|-----------------+-------------------+-------+---------+----------|\n| RegistryHandler | passTime          | 227   | 0       | 0        |\n╰-----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 172797\n  Bound result 92\n  Bound result 87\n  Bound result 89600\n  Bound result 12086\n  Bound result 96\n  Bound result 110519\n\n[PASS] test_handlerReachesEveryOutcome() (gas: 14028842)\nLogs:\n  Bound result 50\n  Bound result 25\n  Bound result 100\n  Bound result 172800\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 760.65ms (764.35ms CPU time)\n\nRan 2 tests for test/StackerInvariantExtended.t.sol:StackerInvariantExtendedTest\n[PASS]\nStackerInvariantExtendedTest invariants:\n[PASS] invariant_imdSupplyConservation\n[PASS] invariant_pauseAndOwnershipStateMachine\n[PASS] invariant_stackerHoldsNothing\n[PASS] invariant_stackerTotals\n[PASS] invariant_vaultConservation\n[PASS] invariant_vaultSolvent\n StackerInvariantExtendedTest invariants (runs: 128, calls: 6144, reverts: 0)\n\n╭-----------------+----------------+-------+---------+----------╮\n| Contract        | Selector       | Calls | Reverts | Discards |\n+===============================================================+\n| ExtendedHandler | advance        | 495   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | credit         | 458   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | creditTiny     | 497   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | depositDirect  | 449   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | donate         | 427   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | faucet         | 469   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | redeem         | 498   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | renounce       | 503   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | rescue         | 477   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | setAllowance   | 480   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | togglePause    | 451   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | transferShares | 452   | 0       | 0        |\n|-----------------+----------------+-------+---------+----------|\n| ExtendedHandler | withdraw       | 488   | 0       | 0        |\n╰-----------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10\n  Bound result 6108\n  Bound result 4665\n  Bound result 50\n  Bound result 19950\n  Bound result 20382\n  Bound result 5291985051657876034\n  Bound result 3696000000\n  Bound result 301\n  Bound result 3734885249580335023744\n  Bound result 14253\n  Bound result 7222\n  Bound result 17513\n  Bound result 7530\n  Bound result 1032\n  Bound result 20398\n  Bound result 2689\n  Bound result 4812\n  Bound result 3423259203365554108621\n  Bound result 3975\n  Bound result 10794\n  Bound result 18149\n  Bound result 280\n  Bound result 19827\n  Bound result 1064470260\n  Bound result 10\n  Bound result 2194\n  Bound result 10774\n  Bound result 9500000000000000000\n  Bound result 1527\n  Bound result 11155111\n  Bound result 512\n  Bound result 4018876662\n  Bound result 20662300\n\n[PASS] test_handlerReachesEveryCreditOutcome() (gas: 4540137)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 5\n  Bound result 100000000000000000000\n  Bound result 1\n  Bound result 50000000000000000000\n  Bound result 7\n  Bound result 24000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 10000000000000000000\n  Bound result 1000000000000000000000\n  Bound result 372757101\n  Bound result 684498244\n  Bound result 1000000000000000000\n  Bound result 2949193105425070115\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.06s (4.06s CPU time)\n\nRan 3 tests for test/RegistryAccountingInvariant.t.sol:RegistryAccountingInvariantTest\n[PASS]\nRegistryAccountingInvariantTest invariants:\n[PASS] invariant_eachActorGetsExactlyTheirEntitlement\n[PASS] invariant_requestsAndListingsMatchIndependentHistory\n RegistryAccountingInvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭---------------------------+----------------------+-------+---------+----------╮\n| Contract                  | Selector             | Calls | Reverts | Discards |\n+===============================================================================+\n| RegistryAccountingHandler | ask                  | 1868  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | donate               | 1769  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | expire               | 1748  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | handOver             | 1829  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | passTime             | 1833  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | reprice              | 1789  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | settle               | 1837  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | unauthorizedOrReplay | 1873  | 0       | 0        |\n|---------------------------+----------------------+-------+---------+----------|\n| RegistryAccountingHandler | unsafeChallenge      | 1838  | 0       | 0        |\n╰---------------------------+----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 27\n  Bound result 14277\n  Bound result 91\n  Bound result 4\n  Bound result 92\n  Bound result 27\n  Bound result 729922641686848800\n  Bound result 0\n  Bound result 3694\n  Bound result 75\n  Bound result 9600\n  Bound result 64\n  Bound result 58\n  Bound result 1051786429938363369\n  Bound result 0\n  Bound result 50\n  Bound result 26656\n  Bound result 835\n  Bound result 1001\n  Bound result 21944\n  Bound result 32\n  Bound result 9379\n  Bound result 9366\n  Bound result 39\n  Bound result 3668\n  Bound result 2\n  Bound result 2960\n  Bound result 53\n  Bound result 171241\n  Bound result 2\n  Bound result 24\n  Bound result 7\n  Bound result 0\n  Bound result 55\n\n[PASS] test_handlerReachesAllPayoutsAndChecksAfterEachTransition() (gas: 31216861)\nLogs:\n  Bound result 25\n  Bound result 1\n  Bound result 100\n  Bound result 0\n  Bound result 50\n  Bound result 0\n  Bound result 50\n  Bound result 1\n  Bound result 50\n  Bound result 0\n  Bound result 50\n  Bound result 2\n  Bound result 50\n  Bound result 3\n  Bound result 50\n  Bound result 4\n  Bound result 50\n  Bound result 172800\n  Bound result 1\n  Bound result 0\n  Bound result 50\n  Bound result 123\n  Bound result 0\n  Bound result 50\n  Bound result 1\n  Bound result 50\n\n[PASS] test_handlerRetainsBeneficiaryPinAcrossHandoffsAndRelisting() (gas: 12707755)\nLogs:\n  Bound result 50\n  Bound result 0\n  Bound result 0\n  Bound result 50\n  Bound result 500000000000000000\n  Bound result 50\n  Bound result 1\n  Bound result 100\n  Bound result 0\n  Bound result 50\n  Bound result 0\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 4.90s (4.92s CPU time)\n\nRan 24 test suites in 4.91s (14.93s CPU time): 150 tests passed, 0 failed, 7 skipped (157 total tests)\n","passed":true},{"durationMs":64,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ProjectRegistry.applyListing(address,string,string,uint16,address)\",\"ProjectRegistry.challenge(address,string)\",\"ProjectRegistry.challengeForBeneficiary(address,string,address)\",\"ProjectRegistry.expire(address)\",\"ProjectRegistry.onOracleFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"ProjectRegistry.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"ProjectRegistry.setBeneficiary(address,address)\",\"Stacker.credit(address,uint256)\"],\"files\":{\".github/ISSUE_TEMPLATE/listing-application.yml\":88,\".gitignore\":4,\"ADAPTATION.md\":99,\"NEXT_SESSION.md\":35,\"README.md\":227,\"docs/design.md\":299,\"docs/explainer.html\":247,\"docs/history.md\":89,\"docs/listing.md\":96,\"foundry.toml\":26,\"jobs/1-sepolia-launch.md\":23,\"jobs/2-sepolia-site.md\":18,\"jobs/3-list-plea.md\":21,\"jobs/4-mainnet-launch.md\":16,\"jobs/5-sepolia-v2-launch.md\":12,\"jobs/5-sepolia-v2-site.md\":10,\"jobs/requests/3-list-plea.json\":10,\"jobs/requests/4-mainnet-launch.json\":31,\"jobs/requests/5-sepolia-v2-launch-only.json\":31,\"jobs/requests/5-sepolia-v2-workflow.json\":50,\"launch.json\":25,\"listings/sepolia.json\":1,\"remappings.txt\":3,\"site/README.md\":63,\"site/app.mjs\":280,\"site/configure.mjs\":13,\"site/core.mjs\":222,\"site/index.html\":61,\"site/style.css\":1,\"site/test/app.test.mjs\":142,\"site/test/browser.mjs\":111,\"site/test/core.test.mjs\":115,\"site/test/fixture.mjs\":97,\"site/test/vendor/linkedom-0.18.12.mjs\":12761,\"site/test/vendor/linkedom-LICENSE\":15,\"site/vendor/ethers-6.17.0.mjs\":1,\"site/vendor/ethers-LICENSE.md\":21,\"src/ProjectRegistry.sol\":607,\"src/Stacker.sol\":98,\"src/oracle/OracleAttestation.sol\":265,\"test/ADVERSARIAL_COVERAGE.md\":41,\"test/Base.t.sol\":58,\"test/Deployment.t.sol\":99,\"test/FactoryRehearsal.t.sol\":47,\"test/MainnetFork.t.sol\":102,\"test/OracleConsumerConformance.t.sol\":140,\"test/ProjectRegistry.t.sol\":587,\"test/ProjectRegistryInvariant.t.sol\":233,\"test/RegistryAccountingInvariant.t.sol\":534,\"test/RegistryAdversarial.t.sol\":446,\"test/RegistryAuditRegression.t.sol\":157,\"test/RegistryBodyProperties.t.sol\":208,\"test/RegistryCallbackGas.t.sol\":111,\"test/RegistryRevisionRegression.t.sol\":325,\"test/RegistrySepoliaFork.t.sol\":111,\"test/SepoliaFork.t.sol\":88,\"test/Stacker.t.sol\":419,\"test/StackerEdges.t.sol\":390,\"test/StackerExternalCalls.t.sol\":257,\"test/StackerInvariant.t.sol\":148,\"test/StackerInvariantExtended.t.sol\":495,\"test/VaultTrustRegression.t.sol\":41,\"test/mocks/MockIntake.sol\":108,\"test/mocks/TestIMD.sol\":41,\"test/mocks/TestSIMD.sol\":178},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"f4a978d3a9153226a2810e9e1c7d2c301524417a770a4a4500f4b1bd7a8e6853","verifiedTreeHash":"ebeb3a904190812cba117e1b9bd1be3d2e39c9a1","verifierVersion":"0.1.0+0e08a464"}]}