{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"a8ff8089-dd8d-44b3-b7c1-763b3da97661","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"5b7511b097ea1b311b2285459d2adde4dd6fb52b3f7e7bb2077b6be55108d15e","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"15128eeb8da9fb5ec13c7964e80f936ddc40e718cc0d455d200435c3dc43d6a7","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"15128eeb8da9fb5ec13c7964e80f936ddc40e718cc0d455d200435c3dc43d6a7","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"496afb817ae7ad08c8d940afc34d944c452fe06019f1133f3795a993f5f87f55","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"107f1e0ccfa37a7c48d267f5442645fa835fc56d8ec7d26d33df0628f76406a6","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"8d6dc333db75a8a3c641e78fdf41b5989a60b570326652a73d87bf24a23fe10c","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"b72293c3366fff3f0b93151bca72cc6cbd189dad31d1ccd1d34dd483f2165a36","skillId":"audit-imported-code","subagents":4,"tools":[]},"key":"audit_imported_code","kind":"code","role":"review","skillHash":"b72293c3366fff3f0b93151bca72cc6cbd189dad31d1ccd1d34dd483f2165a36","skillId":"audit-imported-code","state":"accepted"},{"acceptedSubmissionHash":"4ae4d6b4a9927755b13aba4c585c162727661cbd5a221ece71bfccdfa1700bb9","dependsOn":["adapt_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"b89279670f5a00f5d26286edee00c97dd158b997031350a01cafe6e0329ad227","skillId":"audit-judge","subagents":4,"tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"b89279670f5a00f5d26286edee00c97dd158b997031350a01cafe6e0329ad227","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"4ef65e83e263ac535117928525c57b788760b2210107087da0234b5318f5e600","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"6708d5258f9ccb6a9b66113ffa75cd5dc09f1131b1d893afba3f6afd865778cf","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","subagents":3,"tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"bc5bfc8455464381f2db18badb2b55cf8bec1e535c019349a0378fa990741171","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"639ce3d7b6ba0216157170cc8e6c809d1dec12abaa0f451cd0af0fa28cffa110","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"e010f08e953ac4ae5a2039de70a997ce473fd2fe1fae17013e48aebe61c398e9","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"606842ccca0e7c5d3017a54684625438eab9b351eb51dcf0cf88c43d1ea41464","skillId":"write-foundry-tests","subagents":4,"tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"606842ccca0e7c5d3017a54684625438eab9b351eb51dcf0cf88c43d1ea41464","skillId":"write-foundry-tests","state":"accepted"}],"objective":"Deploy the game Keep the Lights On exactly as it is in this repository: the contract LightsOn (src/LightsOn.sol, which uses src/LightsMath.sol and src/ISqueek.sol), with no token, no pool and no owner. It is a betting game for Squeekchain on Sepolia that settles straight from SqueekCore's rounds of the hamster's wheel. Do not change the game's rules, limits or maths; change only what launching needs, and keep every test in test/ passing (forge test). Constructor: one Config struct, in this order: core = 0x980b4424c007caf7a1f3670b48c8eaef7ebc3d44 (SqueekCore on Sepolia), sqk = 0x5501e1fa81be1c3f49225fa7668da0245d07db60 (SQK on Sepolia), genesisTime = 1793022600, station = 36, startRound = 1000 (a round after his last blackout, while he sleeps). The contract has no admin, no owner, no pause and no upgrade by design. The struct holds only static values, so its ABI encoding is the same as five plain arguments (address, address, uint256, uint256, uint32); if the deployer needs plain arguments, flatten the constructor with the same names, order and values and nothing else. Its own tests, fuzzing, invariants and three earlier audits (money, time, attacks; their proofs are in test/audit_*) are in the repository.","parentJobId":null,"planHash":"1af3ad1683122f17db2f96d4952099cd86baa472c766413904a9106ca19600fb","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"a8ff8089-dd8d-44b3-b7c1-763b3da97661","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2876-src-lightson-sol"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52270","feedbackHash":"eed6e837a11decc9f748f4a0138a7440ebfda58cb49d452abc0b7bad3b8712e0","nodeKey":"adapt_contract_project","submissionHash":"5b7511b097ea1b311b2285459d2adde4dd6fb52b3f7e7bb2077b6be55108d15e","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52595","feedbackHash":"cd791e2d128ff6e7f11bd18888adfe618c2946bbe561dcf6665896eb10ac85bd","nodeKey":"adapt_contract_project","submissionHash":"71e0f8465cb1ed7af0af5e1f41e24bb196bfc1dc5759353d4e1f046c66b630d6","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51522","feedbackHash":"a346c14ba602d2409d190852e136644c8a590671e54329b6309c699a44892538","nodeKey":"audit_economics","submissionHash":"496afb817ae7ad08c8d940afc34d944c452fe06019f1133f3795a993f5f87f55","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51305","feedbackHash":"f20a2856b7ce9a73de05e55261406718da02fa39614762f5d3220e2c43269d80","nodeKey":"audit_flow","submissionHash":"107f1e0ccfa37a7c48d267f5442645fa835fc56d8ec7d26d33df0628f76406a6","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52605","feedbackHash":"6af533d6bb777415a85e5c820e0b39dc8ca6055f862b79638b8e7ba916945dfd","nodeKey":"audit_imported_code","submissionHash":"8d6dc333db75a8a3c641e78fdf41b5989a60b570326652a73d87bf24a23fe10c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"54237","feedbackHash":"82fb724be82f9c234f30d3626826b745cb8323cb83ec6282738fe2fc18f1c94f","nodeKey":"audit_judge","submissionHash":"0ccb7147eb7c80234a4e48da56d49ad40f0af596c3cc335589be92667ac6687a","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52706","feedbackHash":"e3ca191019443e5f8e03766aab61b649946fd3b1dc5ff692075dbe42718e966a","nodeKey":"audit_judge","submissionHash":"4ae4d6b4a9927755b13aba4c585c162727661cbd5a221ece71bfccdfa1700bb9","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51194","feedbackHash":"f24699dd378de2ddc97e9e850c19945228b9a837460b9042f871b50c8ccbd7af","nodeKey":"audit_math","submissionHash":"4ef65e83e263ac535117928525c57b788760b2210107087da0234b5318f5e600","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"53925","feedbackHash":"e894e5a75fecc04f753053873e4d0518c2409b46ee80f06623e9ad2e15c982cc","nodeKey":"audit_permissions","submissionHash":"6708d5258f9ccb6a9b66113ffa75cd5dc09f1131b1d893afba3f6afd865778cf","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52592","feedbackHash":"966564b9afcb5defbafda3b4953cd85ae45539b67cbb69b359dab90ef7e3948f","nodeKey":"manifest","submissionHash":"fba6a89d7aea2e73bf6bb664bb0a9b1fb8d0dacb99604da7dfa0afff1c340f2b","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52548","feedbackHash":"568d767d8444e232fedead33706cc28aed23689b2ce9cb5da893a3a258d32f61","nodeKey":"manifest","submissionHash":"639ce3d7b6ba0216157170cc8e6c809d1dec12abaa0f451cd0af0fa28cffa110","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52214","feedbackHash":"eb8bf58dfee031fff4bc2a826a2b29abd770c96c2e9d1dce7fe4ae4abecddc19","nodeKey":"write_foundry_tests","submissionHash":"e010f08e953ac4ae5a2039de70a997ce473fd2fe1fae17013e48aebe61c398e9","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52289","feedbackHash":"ce601482d83ea05d11d2404b061b6464b06b1cb5b0d44199c5f3365cfbe00036","nodeKey":"write_foundry_tests","submissionHash":"100ed0746fa6d7515d8fd78e84a84ab1bdc1fa0306fc0162ac1f5d77ee2d497a","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"ed7f3ba8d58000b188164511394a41484dd1a0323bf4bbe8ec407bc080a42bcb","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"d2d0460994f47014","findings":[{"citation":"resolved","description":"Merged from audit_permissions (low) and audit_flow (medium): same root cause, kept at the higher severity. In _stall() (src/LightsOn.sol:489-501) the branch taken when the core cannot be read right now decides the stall from `ended > c + STALL_ROUNDS` where c = walker.cursor, the last round LightsOn itself read, and returns mark = c. The cursor moves only when someone calls bet, claim or poke. After a day in which nobody touched the contract, one block in which the core does not answer (a revert, a paused/upgraded core whose reply has another shape, a BadPage) satisfies the 144-round condition at once and flagStall() records stallMark = c, stallUnreadable = true. void() 24 h later only re-runs _stall(): if the core again fails to answer in that one block and nobody poked in between, s is true, unreadable == stallUnreadable, mark == stallMark, walkFirst is false (it is only computed when the core is readable), and the game is voided although the core settled every round in between and still serves the night. The comment at lines 480-481 and RULES.md say an unreadable core is a stall only once that has lasted 144 rounds; the same-kind check added for F1c does not cover two observations both of the unreadable kind. Consequence: a night the core has fully recorded is never read; its winning bets stay WAITING and are refunded at stake while its losing bets are refunded too, so the winner's prize goes back to the losers. The same mechanism applies at launch: START_ROUND is fixed at 1000, so a deployment landing more than 144 rounds after round 1000 is flaggable in its first block whenever the core happens to be unreadable then. Preconditions: the core must fail to answer at two moments at least VOID_DELAY apart (an unprivileged caller cannot cause that against a healthy core since the STALL_GAS guard), and no bet, claim or poke may land between them. The caller of flagStall/void can be the losing bettor. Impact: no stake is lost, but winnings are paid to the wrong party and the game ends irreversibly with no owner to restart it. Minimal fix within the design: record the last round the core was observed readable (the `through` value) whenever _coreState() succeeds on a state-changing path, use base = max(c, lastReadable) in both `ended > base + STALL_ROUNDS` and as `mark`, so an unreadable flag needs 144 rounds since the last successful read and any successful read between flag and void raises the mark and clears the flag, as the behind-kind already does.","line":500,"path":"src/LightsOn.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {LightsOn} from \"src/LightsOn.sol\";\nimport {MockCore, MockSQK} from \"test/mocks/Mocks.sol\";\n\n/// Two one-block read failures of the core, 24 h apart, end a healthy game whose finished night nobody has read.\n/// `_stall` measures the \"unreadable\" stall from the walker's cursor (the last round LightsOn read), not from the\n/// last round the core was known to be readable, so a day without any bet, claim or poke turns a momentary failure\n/// into a 144-round stall. The core answered every block in between and still serves the night.\ncontract UnreadableLagTest is Test {\n    uint256 internal constant G = 1793022600;\n    MockCore internal core;\n    MockSQK internal sqk;\n    LightsOn internal lights;\n    address internal alice = address(0xA11CE);\n    address internal bob = address(0xB0B);\n\n    function setUp() public {\n        core = new MockCore();\n        sqk = new MockSQK();\n        lights = new LightsOn(\n            LightsOn.Config({core: address(core), sqk: address(sqk), genesisTime: G, station: 36, startRound: 0})\n        );\n        _fund(alice);\n        _fund(bob);\n    }\n\n    function _fund(address who) internal {\n        sqk.mint(who, 1_000e18);\n        vm.prank(who);\n        sqk.approve(address(lights), type(uint256).max);\n    }\n\n    function _at(uint256 r) internal {\n        vm.warp(G + (r - 1) * 600 + 100);\n        core.setSettled(uint64(r - 1));\n    }\n\n    function test_twoMomentaryReadFailuresADayApartVoidAnUnreadWin() public {\n        // Round 100: Alice bets bulb 2, Bob bets bulb 10. The walker has read through round 99.\n        _at(100);\n        vm.prank(alice);\n        uint256 a = lights.bet(2, 100e18);\n        vm.prank(bob);\n        uint256 b = lights.bet(10, 100e18);\n        assertEq(lights.getWalker().cursor, 99);\n\n        // He runs 100..105 (5 bulbs), then the blackout 106-107. The core records all of it. Nobody touches LightsOn.\n        core.setActiveRange(100, 105);\n        _at(260); // 259 rounds ended: 259 > 99 + 144\n\n        // One block in which the core cannot be read: Bob flags an \"unreadable\" stall at once.\n        core.setReverting(true);\n        vm.prank(bob);\n        lights.flagStall();\n        core.setReverting(false);\n        assertTrue(lights.stallUnreadable(), \"flag of the unreadable kind\");\n        assertEq(lights.stallMark(), 99, \"mark is the walker's cursor, not anything the core said\");\n\n        // The core is readable for the whole day (anyone could have poked), then fails for one more block.\n        assertFalse(lights.stalled(), \"a readable core that settled every ended round is not stalled\");\n        _at(260 + 145);\n        core.setReverting(true);\n        vm.prank(bob);\n        try lights.void() {} catch {}\n        core.setReverting(false);\n\n        // Expected: the game goes on (void refused or the flag cleared), the night is read and Alice collects her win.\n        assertFalse(lights.voided(), \"a core that answered every block of the 24 h did not stall for 144 rounds\");\n        lights.poke(10);\n        lights.settle(100);\n        assertEq(lights.nightCount(), 1);\n        uint256[] memory ids = new uint256[](2);\n        ids[0] = a;\n        ids[1] = b;\n        lights.claim(ids);\n        assertEq(sqk.balanceOf(alice), 1_000e18 - 100e18 + 198e18, \"Alice: 200 pot less 2% of Bob's 100\");\n        assertEq(sqk.balanceOf(bob), 1_000e18 - 100e18, \"Bob lost\");\n    }\n}","reproduction":"MockCore/MockSQK from test/mocks, LightsOn(core, sqk, G=1793022600, station=36, startRound=0). 1) At round 100 (core settled 99): alice.bet(2, 100e18), bob.bet(10, 100e18); walker.cursor == 99. 2) core.setActiveRange(100,105): departure 100, bulbs 1-5 lit in 101-105, rounds 106-107 quiet (blackout). 3) Warp to round 260 with core settled 259, no call to LightsOn: cursor still 99, 259 ended rounds > 99 + 144. 4) core.setReverting(true) for one block; bob calls flagStall(). Actual: succeeds, stallUnreadable()==true, stallMark()==99. Expected: NotStalled (the core was unreadable for one block, not 144 rounds). core.setReverting(false): stalled() is false again. 5) Warp to round 405 (core settled 404); core.setReverting(true) for one block; bob calls void(). Actual: voided()==true, nightCount()==0, Alice's winning bet stays WAITING and claim pays her 100e18 (stake), Bob gets his 100e18 back. Expected: void() refuses or clears the flag; after poke(10) and settle(100), night 0 is PAID with pool 198e18, Alice collects 198e18 and Bob 0. Variant: any poke between steps 4 and 5 reads the night, moves the cursor past 99 and void() clears the flag, which shows the outcome depends on nobody observing rather than on the core being down. Proof: test/scratch/Proof_c4a3071e3bcb.t.sol fails on this code at assertFalse(voided).","severity":"medium","snippet":"        return (ended > c + STALL_ROUNDS, c, false, true);","title":"Unreadable-kind stall is measured from the walker's cursor, not from the last round the core answered: two momentary read failures a day apart void a game whose finished night nobody read, and the win"},{"citation":"resolved","description":"From audit_economics; reproduced. asleepTooLong() judges the 7-day sleep on certified, ended rounds only (through = min(settledThroughRound, last ended round)), so the round in progress never counts. In the first round of a new ride, before it ends and the core certifies it, the rule still reads as 'not run for 7 days' and void() (line 536) ends the game permanently: bet reverts IsVoided afterwards and nothing can revive it. Every stake in the bonus pot belongs to ROLLED-night losers, and after a void those losers get it back (_claim line 449, _due line 464), so the actor with the strongest incentive to void, a loser with up to 10,000 SQK riding, has a window of one full round (plus certification lag) at the exact moment a ride that would have paid that pot to other bettors begins. The same window is open throughout the preceding sleep; what this adds is that it extends into a ride that has visibly departed. No stake is lost: bettors on the new ride are refunded and lose only their expected prize. This is within the written rule in RULES.md ('if he hasn't run at all for 7 days, anyone can end the game straight away'), so it is a design-level low, not a loss of funds; the author should decide whether the 7-day exit needs a flag-and-wait like the stall exit, or a quiet-current-round condition, before shipping. Any fix changes the 7-day rule and needs the requester's decision.","line":524,"path":"src/LightsOn.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {LightsOn} from \"src/LightsOn.sol\";\nimport {MockCore, MockSQK} from \"test/mocks/Mocks.sol\";\n\n/// The 7-day void (asleepTooLong) is judged on certified rounds only, so it is legal in the round a new ride\n/// departs, while he is visibly running and before the core certifies that round. A loser whose stake rides in the\n/// bonus pot can end the game for good at that moment and take the pot back from the ride that was about to win it.\ncontract VoidDuringDepartureTest is Test {\n    uint256 internal constant G = 1793022600;\n    MockCore core;\n    MockSQK sqk;\n    LightsOn lights;\n    address alice = address(0xA11CE);\n    address bob = address(0xB0B);\n\n    function setUp() public {\n        core = new MockCore();\n        sqk = new MockSQK();\n        lights = new LightsOn(\n            LightsOn.Config({core: address(core), sqk: address(sqk), genesisTime: G, station: 36, startRound: 0})\n        );\n        _fund(alice);\n        _fund(bob);\n    }\n\n    function _fund(address a) internal {\n        sqk.mint(a, 1_000_000e18);\n        vm.prank(a);\n        sqk.approve(address(lights), type(uint256).max);\n    }\n\n    function _at(uint256 r) internal {\n        vm.warp(G + (r - 1) * 600 + 100);\n        core.setSettled(uint64(r - 1));\n    }\n\n    function test_sevenDayVoidIsRefusedWhileTheDepartureRoundIsInProgress() public {\n        _at(97);\n        vm.prank(alice);\n        lights.bet(9, 10_000e18); // loses in a false start: 10,000 rides in the bonus pot\n        core.setActive(100, 10);\n        _at(104);\n        lights.poke(10);\n        lights.settle(100);\n        assertEq(lights.bonusPot(), 10_000e18);\n        vm.prank(bob);\n        uint256 b1 = lights.bet(1, 100e18); // a bet for the next ride\n\n        // 1,009 quiet rounds, then he departs in round 1110; that round is in progress and not certified yet\n        uint256 r = 1110;\n        core.setActive(uint64(r), 500);\n        core.setActive(uint64(r + 1), 500);\n        core.setActive(uint64(r + 2), 500);\n        _at(r);\n        lights.poke(100);\n\n        // Expected: the game cannot be ended by the 7-day rule in a round he is running in.\n        // Actual on this code: asleepTooLong() is true and void() ends the game; bob's bulb 1 lights in 1111 but\n        // he is only refunded, alice takes the 10,000 pot back, and nobody can bet again.\n        vm.prank(alice);\n        (bool ok,) = address(lights).call(abi.encodeCall(LightsOn.void, ()));\n        assertFalse(ok && lights.voided(), \"the 7-day void ended the game in the departure round of a live ride\");\n\n        // the ride goes on and pays as it ended\n        _at(r + 5);\n        lights.poke(100);\n        lights.settle(100);\n        assertEq(lights.nightCount(), 2, \"the departure in 1110 became a night\");\n        (,,,, bool ready) = lights.betOutcome(b1);\n        assertTrue(ready);\n    }\n}","reproduction":"MockCore/MockSQK, LightsOn(core, sqk, G, 36, 0). Round 97: Alice bets bulb 9, 10,000e18. Round 100 active only (false start), rounds 101-103 quiet; at round 104 poke(10)+settle(100): night 0 ROLLED, bonusPot == 10,000e18. Round 104: Bob bets bulb 1, 100e18 (for the next ride). Rounds 105..1109 quiet; rounds 1110, 1111, 1112 active. At 100 s into round 1110 (core settled through 1109), poke(100) then Alice calls void(). Actual: asleepTooLong() is true (through = 1109 > 100 + 1008, cursor == 1109, openStart == 0) and voided() becomes true; Alice claims 10,000e18 back, Bob is refunded 100e18 although his bulb lights in 1111, every later bet reverts IsVoided. Expected (per the economics specialist and the spec's intent that a ride that departed pays as it ends): void() refuses in a round he is running in, and after rounds 1110-1112 are read night 1 is PAID to Bob. Proof: test/scratch/Proof_7e650ea6c50c.t.sol fails on this code with 'the 7-day void ended the game in the departure round of a live ride'.","severity":"low","snippet":"        return w.openStart == 0 && w.cursor >= through && through > awake + SLEEP_ROUNDS;","title":"7-day void (asleepTooLong) is legal in the departure round of a new ride, so a bonus-pot loser can end the game while he is visibly running and take the rolled pot back"}],"hash":"0ccb7147eb7c80234a4e48da56d49ad40f0af596c3cc335589be92667ac6687a","nodeId":"3f2d17b3-498e-4622-a369-1085014ffeca","outcome":"completed","summary":"Review complete. The findings file is written and validated against the tree.\n\n**Verdict on the specialists' four reports**\n\n- **Kept, merged, medium.** The permissions (low) and flow (medium) reports share one root cause at `src/LightsOn.sol:500`. When the core cannot be read, the stall test compares the ended round count against the walker's cursor, which only moves when someone pokes, bets or claims. After a quiet day, one block of an unreadable core is flaggable at once, and a second unreadable block 24 hours later voids the game even though the core settled every round between. The flow proof shows a fully recorded night never being read: the winner is refunded 100 instead of collecting 198, and the loser gets their stake back. Both proof tests fail on the current code for exactly the stated reason. I kept the flow specialist's proof on the merged finding.\n- **Kept, low.** The economics report on the 7-day void at `src/LightsOn.sol:524` reproduces. The sleep check counts only certified, ended rounds, so in the departure round of a new ride a bonus-pot loser can still void and reclaim a rolled stake that the ride was about to pay out. No stake is lost and the behaviour is within the written rule, so it stays a design-level low for the author to decide. Its proof fails on this code and is attached.\n- **Dropped.** The economics \"info\" note about late bets on the nearest winnable bulb carrying weight 3 describes the published weight rule in RULES.md verbatim. It is not a defect and the brief forbids changing the rules.\n\n**My own pass** found nothing further. I traced bet, betUntil, claim, poke, settle, flagStall and void, the walker's night closing, the settlement accounting, the void refund path, the constructor and launch.json. All seven entry points have a coverage row, two marked as findings. Runtime is 16,808 bytes, well inside the limit, and the constructor makes no external calls. The full suite of 133 tests passes.\n\nOne note for the launch rather than a finding: START_ROUND is fixed at 1000 and the author's own test T5 documents that a walker started mid-ride counts the wrong bulbs. Whether round 1000 is still inside a sleep when the factory transaction lands depends on chain state I cannot see.","treeHash":null,"usage":{"cachedInputTokens":799072,"inputTokens":324,"model":"claude-fable-5-1","outputTokens":25099,"runtime":"claude","turns":26,"wallClockMs":1454407}},{"artifacts":[],"attempt":1,"bundleHash":"7b0c8c9485428449cb87529b2d51807a92837ed87991ad47ade9af304312504d","device":"ee9fbaf2480d1034","findings":[],"hash":"100ed0746fa6d7515d8fd78e84a84ab1bdc1fa0306fc0162ac1f5d77ee2d497a","nodeId":"72229d57-2c06-4ce6-828a-e8f5dcf26cfe","outcome":"completed","summary":"I wrote 24 new tests for the LightsOn launch, in three files under `test/`. The full suite passes with `forge build` and `forge test` using the verifier's fuzz seed: 133 tests, 0 failures. The 109 tests that were already there are unchanged. I didn't touch anything outside `test/`, and I found no defects in the contract, so there is no `.imd-findings.json`.\n\nThe files are staged but not committed: git has no author name or email set on this machine, so the commit failed, and I didn't change your git settings. The earlier `imd …` commits suggest the upload step makes the commit itself. If not, the three files are in the staging area ready to commit.\n\n**What the tests use.** They deploy the game the way the launch will: the exact constructor encoding `(0x980b…3d44, 0x5501…db60, 1793022600, 36, 1000)` through a zero-value CREATE2 on an empty chain. Only after deployment do they put the test versions of SqueekCore and SQK at the two Sepolia addresses.\n\n**Invariant tests** (`test/LightsLaunchInvariant.t.sol`, 24 runs × 150 calls). The random calls include:\n- rides, breaks, blackouts, 6-hour ends and sleeps of up to about 8 days;\n- the core going down, stopping recording, and recovering;\n- flagging a stall, trying to end the game, and burns that fail;\n- valid and invalid bets, `betUntil`, and a third party collecting for others, including the same bet twice in one call.\n\nAfter every call these must hold:\n- No SQK is created or lost, and whoever collects for others is never paid.\n- The contract holds exactly what it owes, whether the game is running or has ended. A losing stake still in the bonus pot can't be collected until the game ends, and is paid back in full after.\n- What each player received equals what `betOutcome` says their collected bets were owed, and the total paid out never exceeds the total staked.\n- A settled ride never changes, rides are never removed, and an ended game stays ended.\n- The game never reads rounds at or before 1000 or a round still in progress. Rides don't overlap and last at most 36 rounds.\n- Bets stay in round order, with one bet per wallet per ride.\n\nAt the end of every run the test forces the game to end and collects every bet; the contract must be left holding only SQK that a failed burn couldn't destroy.\n\n**Failure paths** (`test/LightsLaunchFailures.t.sol`, 23 tests). These cover every refusal the contract has:\n- **Bad setup:** zero addresses and ride lengths outside 4–64 are refused; the exact edges 4 and 64 are accepted.\n- **Bad bets:** bulb 0 or 25 and above, amounts below 10 or above 10,000 SQK (plus a fuzz test), a bet before the game starts, a late `betUntil`, and a second bet in the same ride. The exact limits are accepted, and the last 60 seconds of a round count as the next round.\n- **A misbehaving token:** a token that refuses to move funds makes the bet or collect fail, and the bet can still be collected later. A token that calls back into the game is blocked.\n- **A misbehaving core:** broken pages are rejected and the game reads nothing from them, while bets and collects still work. Rounds not yet recorded can't be checked for activity.\n- **Stall and ending the game:** the stall check refuses to run without enough gas, a short outage isn't a stall, ending is refused before the 24-hour wait, and a stall flag is cleared if the core recovers. A ride that has ended must be settled before the game can end, and it pays as it ended.\n- **Collecting:** unknown or not-yet-settled bets are skipped, and a stake rolled into the bonus pot can't be collected while the game runs.\n\nThree failures I hit while writing these were mistakes in my test harness, not the contract, and I fixed them:\n- A `vm.prank` was used up by a read call made before the bet.\n- I forgot that placing a bet can settle a ride and burn SQK, which changed the balance I was checking.\n- One test step moved time backwards, which can't happen on chain.\n\nThe shared deploy helper is `test/LightsLaunchFixture.sol`.","treeHash":"7fe9591a92e6b07943b867a57e7c0f3cca407d91","usage":{"cachedInputTokens":1685073,"inputTokens":45,"model":"claude-opus-5-5","outputTokens":41011,"runtime":"claude","turns":25,"wallClockMs":898568}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"4576f670afa0131d","findings":[{"citation":"resolved","description":"In _stall() (src/LightsOn.sol:489-501) the branch taken when the core cannot be read right now decides the stall from `ended > c + STALL_ROUNDS` where `c` is walker.cursor, the last round LightsOn itself read, and reports `mark = c`. The cursor only moves when someone calls bet, claim or poke. So after a day in which nobody touched the contract, a single block in which the core does not answer (a revert, an out-of-shape reply, an upgrade in flight) satisfies the 144-round condition at once, and flagStall() records an unreadable-kind flag with stallMark = c. void() 24 h later only re-runs _stall(): if the core again fails to answer in that one block and nobody poked in between, `s` is true, `unreadable == stallUnreadable`, `mark == stallMark`, walkFirst is false (it is only computed when the core is readable), and the game is voided. The core answered every other block of those 24 h and still serves the night that ended before the first failure, so the rule the comment on stalled() states (a revert or a reply LightsOn cannot read is not a stall by itself; it must last 144 rounds) is broken, and the F1c fix (same-kind check) does not cover the case where both observations are of the unreadable kind. Consequence: a night the core has fully recorded is never read; its winning bets stay WAITING and are refunded at stake, its losing bets are refunded too, so winnings move from the winner back to the losers. Preconditions, stated honestly: the core must fail to answer at two moments at least VOID_DELAY apart (an unprivileged caller cannot cause that against a healthy core: A4 fixed gas starvation, and every live Sepolia page from round 0 to 1005 passes readCorePage), and no bet, claim or poke may land between the two moments. The caller of flagStall and void can be the losing bettor. Suggested minimal fix that keeps the design: count the unreadable-kind stall from the last round the core was observed readable instead of from the cursor. Store `lastReadable` (the `through` value) whenever _coreState() succeeds on a state-changing path (_poke, flagStall, void), use `base = max(c, lastReadable)` both in `ended > base + STALL_ROUNDS` and as `mark`, and have flagStall/void record lastReadable when _stall() finds the core readable. Then an unreadable flag needs 144 rounds since the last successful read, and any successful read between flag and void raises the mark and clears the flag, as the behind-kind already does. The residual (a contract nobody calls for a day observes nothing) belongs in the README so the page pokes on a timer.","line":500,"path":"src/LightsOn.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {LightsOn} from \"src/LightsOn.sol\";\nimport {MockCore, MockSQK} from \"test/mocks/Mocks.sol\";\n\n/// Two one-block read failures of the core, 24 h apart, end a healthy game whose finished night nobody has read.\n/// `_stall` measures the \"unreadable\" stall from the walker's cursor (the last round LightsOn read), not from the\n/// last round the core was known to be readable, so a day without any bet, claim or poke turns a momentary failure\n/// into a 144-round stall. The core answered every block in between and still serves the night.\ncontract UnreadableLagTest is Test {\n    uint256 internal constant G = 1793022600;\n    MockCore internal core;\n    MockSQK internal sqk;\n    LightsOn internal lights;\n    address internal alice = address(0xA11CE);\n    address internal bob = address(0xB0B);\n\n    function setUp() public {\n        core = new MockCore();\n        sqk = new MockSQK();\n        lights = new LightsOn(\n            LightsOn.Config({core: address(core), sqk: address(sqk), genesisTime: G, station: 36, startRound: 0})\n        );\n        _fund(alice);\n        _fund(bob);\n    }\n\n    function _fund(address who) internal {\n        sqk.mint(who, 1_000e18);\n        vm.prank(who);\n        sqk.approve(address(lights), type(uint256).max);\n    }\n\n    function _at(uint256 r) internal {\n        vm.warp(G + (r - 1) * 600 + 100);\n        core.setSettled(uint64(r - 1));\n    }\n\n    function test_twoMomentaryReadFailuresADayApartVoidAnUnreadWin() public {\n        // Round 100: Alice bets bulb 2, Bob bets bulb 10. The walker has read through round 99.\n        _at(100);\n        vm.prank(alice);\n        uint256 a = lights.bet(2, 100e18);\n        vm.prank(bob);\n        uint256 b = lights.bet(10, 100e18);\n        assertEq(lights.getWalker().cursor, 99);\n\n        // He runs 100..105 (5 bulbs), then the blackout 106-107. The core records all of it. Nobody touches LightsOn.\n        core.setActiveRange(100, 105);\n        _at(260); // 259 rounds ended: 259 > 99 + 144\n\n        // One block in which the core cannot be read: Bob flags an \"unreadable\" stall at once.\n        core.setReverting(true);\n        vm.prank(bob);\n        lights.flagStall();\n        core.setReverting(false);\n        assertTrue(lights.stallUnreadable(), \"flag of the unreadable kind\");\n        assertEq(lights.stallMark(), 99, \"mark is the walker's cursor, not anything the core said\");\n\n        // The core is readable for the whole day (anyone could have poked), then fails for one more block.\n        assertFalse(lights.stalled(), \"a readable core that settled every ended round is not stalled\");\n        _at(260 + 145);\n        core.setReverting(true);\n        vm.prank(bob);\n        try lights.void() {} catch {}\n        core.setReverting(false);\n\n        // Expected: the game goes on (void refused or the flag cleared), the night is read and Alice collects her win.\n        assertFalse(lights.voided(), \"a core that answered every block of the 24 h did not stall for 144 rounds\");\n        lights.poke(10);\n        lights.settle(100);\n        assertEq(lights.nightCount(), 1);\n        uint256[] memory ids = new uint256[](2);\n        ids[0] = a;\n        ids[1] = b;\n        lights.claim(ids);\n        assertEq(sqk.balanceOf(alice), 1_000e18 - 100e18 + 198e18, \"Alice: 200 pot less 2% of Bob's 100\");\n        assertEq(sqk.balanceOf(bob), 1_000e18 - 100e18, \"Bob lost\");\n    }\n}","reproduction":"Mock setup as in test/LightsBase.t.sol (station 36, startRound 0). 1) _at(100): alice.bet(2, 100e18), bob.bet(10, 100e18); walker.cursor == 99. 2) core.setActiveRange(100,105): departure 100, bulbs 1-5 lit in 101-105, rounds 106-107 quiet (blackout). 3) _at(260) with no call to LightsOn: cursor still 99, 259 ended rounds. 4) core.setReverting(true) for one block; bob calls flagStall(): it succeeds, stallUnreadable()==true, stallMark()==99. core.setReverting(false); lights.stalled() is now false because the core settled every ended round. 5) _at(405): core.setReverting(true) for one block; bob calls void(). Actual: voided()==true, nightCount()==0, the winning bet is still WAITING and claim() pays its owner 100e18 (the stake); Bob gets his 100e18 back. Expected: void() refuses or clears the flag; after poke(10) and settle(100) night 0 is PAID with pool 198e18, claim pays the winner 198e18 and Bob 0. Variant: if any poke lands between steps 4 and 5 the walker reads the night, the cursor passes 99 and void() clears the flag, which shows the outcome depends on nobody observing rather than on the core being down. Proof test: test/scratch/UnreadableLag.t.sol (fails on the current code at the assertFalse(voided) line).","severity":"medium","snippet":"        return (ended > c + STALL_ROUNDS, c, false, true);","title":"Unreadable-kind stall is measured from the walker cursor, so two momentary core read failures a day apart void a game whose finished night nobody read (winner refunded at stake)"}],"hash":"107f1e0ccfa37a7c48d267f5442645fa835fc56d8ec7d26d33df0628f76406a6","nodeId":"1006f333-1a33-4046-8ed6-2ecb3cabac9f","outcome":"completed","summary":"Review complete. The findings file is written and its quoted snippet matches `src/LightsOn.sol:500` exactly. Git itself is unavailable in this sandbox (the gitconfig read is denied), but the only files I created are `.imd-findings.json` and the scratch proof test under `test/scratch/`, which the assignment allots to me.\n\n**Outcome: one medium finding, control-flow area otherwise holds.**\n\n- **Finding 1 (medium), `src/LightsOn.sol:500`.** The \"unreadable\" stall branch counts the 144 rounds from the walker's cursor, which only moves when someone calls bet, claim or poke. After a day with no calls, one block in which the core does not answer lets anyone flag a stall at once, and one more such block 24 h later lets `void()` end the game, even though the core answered every block in between and still serves a finished night nobody read. The winner of that night is refunded at stake and the loser gets their stake back. I state the preconditions plainly: the core must fail at two moments a day apart, which an unprivileged caller cannot cause against a healthy core, and nobody may poke in between. The proof test fails on the current code at the \"not voided\" assertion. The existing F1c regression covers only the mixed case (a lag flag followed by an unreadable moment). Suggested fix: measure the unreadable kind from the last round the core was observed readable, recorded on every successful read.\n\n**What I verified and found sound**\n\n- All 109 existing tests pass, including invariants at 48 runs by depth 200.\n- Bet ordering, night-run completeness at settlement, the 64-bit night bitmap, the one-bet-per-night check, partial settle resumption, claim readiness and the bonus-pot accounting after a void all trace correctly.\n- Reentrancy: core reads are staticcalls through self-calls with fixed gas; the money-moving entry points are guarded.\n- Live Sepolia checks against the real SqueekCore: time-based round 1006 matches the core's settled round 1005, every page from round 0 to 1005 passes the walker's `BadPage` rules, `afterRound` is exclusive, and rounds 999 to 1005 are quiet, so the start round of 1000 is valid.\n\n**Coverage record:** all seven entry points have rows (five `holds`, `flagStall` and `void` marked `finding`), plus four invariant rows. Nothing in my area was left unreached.","treeHash":null,"usage":{"cachedInputTokens":1556562,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":58614,"runtime":"claude","turns":29,"wallClockMs":937913}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"fd7c32744e171d7d","findings":[{"citation":"resolved","description":"asleepTooLong() judges the 7-day sleep on certified rounds only (through = min(settledThroughRound, last ended round)). The round in progress is never part of that window, so in the first round of a new ride, before the core certifies it, the rule still reads as 'not run for 7 days' and void() (line 536) ends the game permanently. Economics: every stake riding in the bonus pot belongs to ROLLED-night losers, and after a void those losers get it back (claim, line 449/464). So the actor with the strongest incentive to void, a loser with up to 10,000 SQK riding, has a legal window of one full round (10 minutes, plus however long the core takes to certify) at the exact moment a ride that would have paid that pot to other bettors begins. Bettors on the new ride lose nothing but their expected prize; the game is dead afterwards (bet reverts IsVoided) and nothing can revive it. This is within the written rule ('if he hasn't run at all for 7 days, anyone can end the game straight away'), so it is a design-level low, not a loss of funds: the author should decide whether the 7-day exit needs a flag-and-wait like the stall exit, or a check that the current round is quiet, before shipping. Stall-path void already has such protection (24 h after a flag, cleared if the core moves).","line":524,"path":"src/LightsOn.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {LightsOn} from \"src/LightsOn.sol\";\nimport {MockCore, MockSQK} from \"test/mocks/Mocks.sol\";\n\n/// The 7-day void (asleepTooLong) is judged on certified rounds only, so it is legal in the round a new ride\n/// departs, while he is visibly running and before the core certifies that round. A loser whose stake rides in the\n/// bonus pot can end the game for good at that moment and take the pot back from the ride that was about to win it.\ncontract VoidDuringDepartureTest is Test {\n    uint256 internal constant G = 1793022600;\n    MockCore core;\n    MockSQK sqk;\n    LightsOn lights;\n    address alice = address(0xA11CE);\n    address bob = address(0xB0B);\n\n    function setUp() public {\n        core = new MockCore();\n        sqk = new MockSQK();\n        lights = new LightsOn(\n            LightsOn.Config({core: address(core), sqk: address(sqk), genesisTime: G, station: 36, startRound: 0})\n        );\n        _fund(alice);\n        _fund(bob);\n    }\n\n    function _fund(address a) internal {\n        sqk.mint(a, 1_000_000e18);\n        vm.prank(a);\n        sqk.approve(address(lights), type(uint256).max);\n    }\n\n    function _at(uint256 r) internal {\n        vm.warp(G + (r - 1) * 600 + 100);\n        core.setSettled(uint64(r - 1));\n    }\n\n    function test_sevenDayVoidIsRefusedWhileTheDepartureRoundIsInProgress() public {\n        _at(97);\n        vm.prank(alice);\n        lights.bet(9, 10_000e18); // loses in a false start: 10,000 rides in the bonus pot\n        core.setActive(100, 10);\n        _at(104);\n        lights.poke(10);\n        lights.settle(100);\n        assertEq(lights.bonusPot(), 10_000e18);\n        vm.prank(bob);\n        uint256 b1 = lights.bet(1, 100e18); // a bet for the next ride\n\n        // 1,009 quiet rounds, then he departs in round 1110; that round is in progress and not certified yet\n        uint256 r = 1110;\n        core.setActive(uint64(r), 500);\n        core.setActive(uint64(r + 1), 500);\n        core.setActive(uint64(r + 2), 500);\n        _at(r);\n        lights.poke(100);\n\n        // Expected: the game cannot be ended by the 7-day rule in a round he is running in.\n        // Actual on this code: asleepTooLong() is true and void() ends the game; bob's bulb 1 lights in 1111 but\n        // he is only refunded, alice takes the 10,000 pot back, and nobody can bet again.\n        vm.prank(alice);\n        (bool ok,) = address(lights).call(abi.encodeCall(LightsOn.void, ()));\n        assertFalse(ok && lights.voided(), \"the 7-day void ended the game in the departure round of a live ride\");\n\n        // the ride goes on and pays as it ended\n        _at(r + 5);\n        lights.poke(100);\n        lights.settle(100);\n        assertEq(lights.nightCount(), 2, \"the departure in 1110 became a night\");\n        (,,,, bool ready) = lights.betOutcome(b1);\n        assertTrue(ready);\n    }\n}","reproduction":"Mock core/token as in test/mocks. Round 97: Alice bets bulb 9, 10,000 SQK. Round 100 active only (false start), rounds 101-103 quiet; poke+settle: night 0 ROLLED, bonusPot = 10,000. Round 104: Bob bets bulb 1, 100 SQK (for the next ride). Rounds 101..1109 quiet; rounds 1110, 1111, 1112 active. At 100 s into round 1110 (core settled through 1109), anyone calls poke(100) then void(): asleepTooLong() is true (through = 1109 > 100 + 1008) and voided becomes true. Expected: a ride that has departed cannot be voided by the 7-day rule. Actual: Alice claims 10,000 back, Bob is refunded 100 although his bulb lights in 1111, and every later bet reverts IsVoided. test/scratch/VoidDuringDeparture.t.sol fails on this code with 'the 7-day void ended the game in the departure round of a live ride'.","severity":"low","snippet":"        return w.openStart == 0 && w.cursor >= through && through > awake + SLEEP_ROUNDS;","title":"7-day void is legal in the departure round of a new ride: a bonus-pot loser can end the game while he is visibly running and take the pot back"},{"citation":"resolved","description":"litBefore counts bulbs lit strictly before the bet's round (LightsOn._litBefore, line 643), and the lowest bulb that can still win is the one lighting in betRound + 2. So at any round N of a ride with k bulbs lit through N-1, a bet on bulb k+3 has weight stake x 3 and needs only rounds N+1 and N+2 to be active, while a bet on bulb 3 placed before the ride also has weight stake x 3 but needed the departure plus three more rounds. The pot is shared by weight, so the late two-rounds-ahead bet dominates the early low-bulb bet on both risk and share; the information advantage of watching him live is priced at exactly zero for that bulb. This is the published rule (RULES.md: weight = bet x (bulb - litBefore)) and no funds are lost or misdirected, so it is reported as an economic observation only, not a defect to fix without a rules decision.","line":41,"path":"src/LightsMath.sol","reproduction":"Mock core: rounds 100..130 active. Round 97: Alice bets bulb 3, 100 SQK. Round 120 (bulbs 1-19 lit through 119): Bob bets bulb 22, 100 SQK (lights in 122 = N+2). Round 135: poke, settle. Both are WIN; getBet(alice).bulb - litBefore = 3 - 0 = 3, getBet(bob).bulb - litBefore = 22 - 19 = 3; each is paid exactly 100 SQK (equal weights, no losers). Expected by the rules: identical weights (confirmed). Observation: Bob carried two rounds of risk, Alice four, for the same share.","severity":"info","snippet":"        return stake * (bulb - litBefore);","title":"Weight rule gives every late bettor a fixed weight of 3 for the nearest winnable bulb, equal to an early bulb-3 bet that carried four rounds of risk"}],"hash":"496afb817ae7ad08c8d940afc34d944c452fe06019f1133f3795a993f5f87f55","nodeId":"6498655f-5176-4c97-b908-5eb269dd3e58","outcome":"completed","summary":"The review is complete and the findings file is in place. Nothing in the repository was changed: the only files I created are the untracked `.imd-findings.json` and one scratch test under `test/scratch/`, which is not kept.\n\n**Outcome.** The economics of LightsOn hold. I found no loss, misdirection or stranding of funds in the settlement maths, the bonus-pot chain, the burn, the claims or the void refunds. The full repository suite passes on this tree (109 tests, including the invariant run at 48 runs by 200 depth). I report one low finding and one informational observation.\n\n**Finding 1, low.** The 7-day void is judged on certified rounds only, so it is legal in the round a new ride departs, before the core certifies that round. The actor with the strongest incentive to use it is a loser whose stake rides in the bonus pot, because a void hands that pot back to such losers. The reproduction and a proof test are in the findings file. The proof test fails on the current code and expects void to be refused while the departure round is in progress. This is within the written rule, so it is a design decision for the author, not a loss of funds.\n\n**Finding 2, info.** The weight rule gives any late bet on the nearest winnable bulb a fixed weight of 3, equal to an early bulb-3 bet that carried four rounds of risk. It is the published rule and moves no funds; it is recorded as an economic observation only.\n\n**What I covered.** All seven entry points have coverage rows: six hold and void carries finding 1. I also recorded rows for the three money invariants and for both live dependencies. I checked the Sepolia SQK bytecode selectors and the live core pages: SQK is a plain OpenZeppelin ERC20 with permit and burn, no pause, owner or proxy; the core is settled through round 1005 and rounds 985 to 1005 are quiet, so the start round 1000 is after a blackout as the brief requires.\n\n**Not reached.** I did not fork Sepolia to exercise the real token and core end to end; the dependency rows rest on bytecode selector inspection, live read calls and the earlier adaptation's checks. Everything else in my area was traced in the source.","treeHash":null,"usage":{"cachedInputTokens":1600053,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":55094,"runtime":"claude","turns":32,"wallClockMs":943420}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"f3b611cf8afb513f","findings":[],"hash":"4ae4d6b4a9927755b13aba4c585c162727661cbd5a221ece71bfccdfa1700bb9","nodeId":"3f2d17b3-498e-4622-a369-1085014ffeca","outcome":"completed","summary":"Both earlier findings are settled and no new defect was found. The review is written to `.imd-findings.json` with an empty findings list and ten coverage rows.\n\n**Finding 4e170c77 (unreadable stall measured from the cursor): fixed, dropped.** The revision adds `readThrough` and measures the unreadable kind from the later of the cursor and that value at src/LightsOn.sol:509. The author's regression test fails on the old code and passes now. I ran my attached proof on the revised code and it still fails, but the author's dispute holds. In the proof, the contract's storage and the core's replies at the flag block and the void block are identical to those of a core that died at round 99. No deterministic contract can tell the two apart. Passing the proof would require refusing unreadable-kind voids in general, which locks every stake on a dead core, or a new stall rule the brief forbids. My own suggested fix would not pass it either. The residual, that a contract nobody calls for a day observes nothing, is inherent to a design with no admin.\n\n**Advisory 70922547 (7-day void in a departure round): written rule, dropped.** It still reproduces, but the core cannot serve the round in progress, so the rule applies to certified rounds as RULES.md states. Any fix changes the 7-day rule, and the author has recorded it in ADAPTATION.md as an open question for the requester.\n\n**Checks run:**\n\n- All four attached proofs under test/scratch/ fail on the revised code for the reasons above.\n- Full suite: 141 tests passed, 0 failed.\n- LightsOn runtime size 16,956 bytes, initcode 17,517 bytes, both under the protocol limits.\n- launch.json has only kind, contracts and notes, with the brief's five static constructor words in Config field order. The constructor makes no external call, so it deploys on an empty chain.\n\nAll seven entry points are marked `holds` in the coverage record. The scratch directory was removed and the tree is clean apart from the findings file.","treeHash":null,"usage":{"cachedInputTokens":347911,"inputTokens":162,"model":"claude-fable-5-1","outputTokens":11290,"runtime":"claude","turns":13,"wallClockMs":315325}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"2f1d693f218c1c18","findings":[],"hash":"4ef65e83e263ac535117928525c57b788760b2210107087da0234b5318f5e600","nodeId":"976cccc1-c2e0-469a-b620-665f5c036628","outcome":"completed","summary":"The review is complete. The findings file holds an empty findings list and nine coverage rows, and the scratch tests are deleted.\n\n**Outcome:** no arithmetic, boundary or numerical-gap defect was substantiated in `src/LightsOn.sol` or `src/LightsMath.sol`.\n\n**What I checked**\n\n- **Math Precision.** The burn is a floor of 2% of what winners take, and it never truncates to zero above the 10 SQK minimum. Winner shares are differences of cumulative floors in bet order, so they telescope to the exact pool. Every downcast was bounded by hand: rounds fit uint32, stakes fit uint96, and weight sums stay far below uint128 even at ten thousand maximum bets on bulb 24.\n- **Boundary.** The bit shifts in the walker and in the lit-before mask are bounded by the station length minus one, which the constructor caps at 63. I read the live SqueekCore on Sepolia and confirmed a full 16-record page ends at its last record's position, an empty page has equal start and end positions, and `state()` returns eight words, so `readCorePage` accepts real pages. SQK exposes burn, transfer and transferFrom with boolean returns and has no pause selector.\n- **Numerical Gap.** The bonus pot always equals the losing stakes of ROLLED nights after the last PAID night, which is what a void refunds. A settle budget that ends exactly on a night's last bet completes the night on the next call without double counting. Bets in a night's last two rounds can only refund or lose, which matches the rules.\n\n**Verification.** The full suite passed, 109 tests including the invariant run with zero reverts. Four scratch tests I wrote for the seams above also passed, then were removed.\n\n**Noted, not a defect.** The stall threshold requires 145 ended rounds behind, not 144. An existing audit test asserts this reading, so it is the author's documented intent.\n\nAll seven entry points are marked as holding, with reasons, plus two invariant rows.","treeHash":null,"usage":{"cachedInputTokens":962521,"inputTokens":52,"model":"claude-fable-5-1","outputTokens":45883,"runtime":"claude","turns":34,"wallClockMs":651248}},{"artifacts":[],"attempt":1,"bundleHash":"b8589cf986c2120929875172c2be44b885b1207840cb902ee174a1e24205d06e","device":"f9a12c57a094ca8d","findings":[],"hash":"5b7511b097ea1b311b2285459d2adde4dd6fb52b3f7e7bb2077b6be55108d15e","nodeId":"db568053-197c-4e2e-a57b-09c5a9e58788","outcome":"completed","summary":"Revision complete. Both findings reproduced; one is fixed at its root cause but its proof is disputed, and the other is left as the requester's rule.\n\n**Medium finding (unreadable stall measured from the cursor)**\n\nThe proof fails on the starting tree. The named root cause is real in one family of cases and is now fixed in `src/LightsOn.sol`:\n\n- New `readThrough` storage records the last round the core had settled whenever the walker read it without a failure. A failed page, or a `poke(0)` with rounds still unread, records nothing.\n- The unreadable-kind stall and its mark now count from max(cursor, readThrough) instead of the cursor alone. A bet reads one page and a collect two, so after a long run the cursor could lag a core that was read fine in the same block, and one failed read a block later counted as a 144-round stall. That no longer happens.\n- I did not use the reviewer's literal suggestion (record every successful `state()` call). It would push the mark forward on each bet while pages are unreadable, so the T2b exit would never open and funds would lock. A regression test pins this.\n\nThe proof itself is **disputed** and still fails on the result. Its history is indistinguishable to the contract from the suite's canonical stall-and-void: same storage at the flag block, same non-answer at the void block, and no state-changing call in between (the proof's only call is the view `stalled()`). A deterministic contract cannot void in one case and refuse in the other. Passing it would require refusing the unreadable-kind void in general (locking funds behind a permanently unreadable core, contradicting T2b and RULES.md), a new stall rule (forbidden by the brief, and the proof itself requires the first flag to succeed), or making `stalled()` write state to game the test. The reviewer's own suggested fix does not pass the proof either. All of this is written in `.imd-responses.json` and ADAPTATION.md.\n\n**Low advisory (7-day void in a departure round)**\n\nReproduced in a scratch test exactly as described. Left alone and answered \"disputed\": it is the written 7-day rule applied to certified rounds, the core cannot serve the round in progress, and any fix changes the rule, which the brief forbids and the reviewer agrees is the requester's call. Recorded as an open design question in ADAPTATION.md.\n\n**Verification**\n\n| Check | Result |\n|---|---|\n| `forge build` | passes, runtime 16,956 bytes, no link references |\n| full `forge test` with the verifier's seed | 114 passed, 0 failed, 14 suites |\n| new `test/audit_review/ReviewFindings.t.sol` | 5 tests; the page-budget test fails on the old code, passes now |\n| reviewer's proof | fails on both trees, disputed as above |\n\nFiles changed: `src/LightsOn.sol`, `test/audit_review/ReviewFindings.t.sol` (new), `ADAPTATION.md`, `README.md`, `.imd-responses.json`. Nothing protected was touched.","treeHash":"64b23d649ba283b4b281bc15c1afe2e9861cff28","usage":{"cachedInputTokens":2151625,"inputTokens":706,"model":"claude-fable-5-1","outputTokens":50314,"runtime":"claude","turns":43,"wallClockMs":1069718}},{"artifacts":[],"attempt":1,"bundleHash":"406ae47ec625fab9e4644dc36b801d9d4f5473c9ae958ce92b43bd50a7ff5e3e","device":"9b657b3675e34ec5","findings":[],"hash":"639ce3d7b6ba0216157170cc8e6c809d1dec12abaa0f451cd0af0fa28cffa110","nodeId":"56c465ab-240b-4d63-9fe5-776092e6a602","outcome":"completed","summary":"The manifest is done and verified. Only launch.json changed.\n\n**What I found.** The previous round's launch.json already matched the brief: one contract, LightsOn, with five static words for the Config struct in declaration order. The other contributor's later commit added the `readThrough` stall fix to the source, but it did not touch the constructor, so no constructor argument needed revising. The brief listed no concrete findings.\n\n**What I changed.** I expanded the notes to name each Config field's type and to state that the accepted revision 2 source left the constructor, limits and maths unchanged. The arguments themselves are the same as before.\n\n| Field | Value |\n|---|---|\n| core | 0x980b4424c007caf7a1f3670b48c8eaef7ebc3d44 |\n| sqk | 0x5501e1fa81be1c3f49225fa7668da0245d07db60 |\n| genesisTime | 1793022600 |\n| station | 36 |\n| startRound | 1000 |\n\n**Checks run.**\n- `forge build` compiles cleanly on solc 0.8.26.\n- `forge test` with the verifier's fuzz seed passes all 114 tests, including the invariant suite and the six launch rehearsal tests that deploy the exact manifest encoding through a factory-style CREATE2 on an empty chain.\n- A schema check confirms only the keys kind, contracts and notes, a 32-character identifier, string arguments, one entry per Config field matching the compiled ABI, and notes under 4000 characters.\n- `git status` shows launch.json as the only modified file. No owner argument exists because the game has none by design, so `$owner` is correctly absent.","treeHash":"83f32e763b4e6410aba0ba2f58e21c9baeecfb14","usage":{"cachedInputTokens":200199,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":4239,"runtime":"claude","turns":8,"wallClockMs":184858}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"96ecbe9236c400bb","findings":[{"citation":"resolved","description":"Area: Access Control (the guard on the unprivileged flagStall()/void() kill switch reads a slot, walker.cursor, that depends on nobody having called poke, not on the core). The spec and the comment at src/LightsOn.sol:480-481 say a core that cannot be read is a stall only once that has lasted 144 rounds. When _coreState() or the single page read fails, _stall() returns `ended > walker.cursor + STALL_ROUNDS`. walker.cursor advances only when someone pokes (directly, or through bet/claim). During a quiet spell (he sleeps, nobody bets or claims) the cursor stays where the last poke left it while the core keeps settling every round, so after 145 rounds of a healthy core the guard is already satisfied and any single block in which the core reverts, has no code or returns a page LightsOn rejects lets anyone call flagStall() at once (stallMark = stale cursor, stallUnreadable = true). void() 24 h later only compares mark (still the same stale cursor if nobody poked) and the unreadable mode, so a second single-block unreadability a day later voids the game permanently, although the core settled every round in between. The same mechanism applies at launch: START_ROUND is fixed at 1000, so if the deployment lands more than 144 rounds after round 1000, the game is flaggable in its very first block if the core happens to be unreadable then. Trigger: the core being unreadable is not something an unprivileged caller can cause (A4 fixed the gas-starvation route); it needs the core's operator (a pause that makes state()/roundPage revert, an upgrade window) or an outage. The unprivileged part is the inaction that leaves the cursor stale, which is normal during a sleep week, and the fact that flagStall/void are open to anyone. Impact: no funds are lost (void refunds), but the game ends irreversibly, there is no owner to restart it, and the documented 144-round guarantee does not hold. Rated low because the trigger is an external privileged or operational event. Possible fix within the design: when the core is unreadable, measure from the moment unreadability was first observed (record it in flagStall as a two-step: first observation starts a 144-round clock, the flag is accepted only when it has lasted), or require `through > c` to have persisted, rather than comparing against walker.cursor.","line":500,"path":"src/LightsOn.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {LightsOn} from \"src/LightsOn.sol\";\nimport {MockCore, MockSQK} from \"test/mocks/Mocks.sol\";\n\n/// Permissions audit: the \"unreadable for 144 rounds\" stall guard in LightsOn._stall (src/LightsOn.sol:500) is\n/// measured from the walker's own cursor, which nobody's inaction leaves stale, not from how long the core has\n/// actually been unreadable. This test FAILS on the current code: a core that was healthy and fully settled for\n/// 146 rounds, and unreadable for a single block, is flagged at once and the game can be voided after two such\n/// blocks a day apart. It passes once a stall needs 144 rounds of real unreadability (or of the core being behind).\ncontract StaleCursorFlagTest is Test {\n    uint256 internal constant G = 1793022600;\n    MockCore internal core;\n    MockSQK internal sqk;\n    LightsOn internal lights;\n\n    function setUp() public {\n        core = new MockCore();\n        sqk = new MockSQK();\n        lights = new LightsOn(\n            LightsOn.Config({core: address(core), sqk: address(sqk), genesisTime: G, station: 36, startRound: 1000})\n        );\n    }\n\n    /// 100 s into round r, with every earlier round settled by the core.\n    function _at(uint256 r) internal {\n        vm.warp(G + (r - 1) * 600 + 100);\n        core.setSettled(uint64(r - 1));\n    }\n\n    function test_oneBlockRevertIsNotAStallWhenNobodyPokedForADay() public {\n        _at(1001);\n        assertEq(lights.poke(10), 0, \"nothing to read yet\");\n        assertEq(lights.getWalker().cursor, 1000);\n\n        // 146 rounds later the core is healthy and has settled every round; nobody poked (he sleeps, no bets)\n        _at(1147);\n        assertFalse(lights.stalled(), \"readable and current: not a stall\");\n\n        core.setReverting(true); // the core is unreadable for this one block\n        assertFalse(lights.stalled(), \"unreadable for one block, not 144 rounds: not a stall\");\n        vm.expectRevert(LightsOn.NotStalled.selector);\n        lights.flagStall();\n        assertEq(lights.stallFlaggedAt(), 0, \"no flag after one block of unreadability\");\n        core.setReverting(false);\n\n        // the core keeps settling every round for a day; a second one-block revert 24 h later\n        _at(1147 + 144);\n        assertFalse(lights.stalled(), \"the core is healthy again\");\n        core.setReverting(true);\n        vm.expectRevert(LightsOn.TooEarly.selector);\n        lights.void();\n        assertFalse(lights.voided(), \"two single-block reverts a day apart must not end the game\");\n    }\n}","reproduction":"Deploy LightsOn(core=MockCore, sqk=MockSQK, genesisTime=1793022600, station=36, startRound=1000). 1) warp to round 1001 (core settled 1000), poke(10): cursor stays 1000. 2) warp to round 1147 with core.setSettled(1146), nobody pokes: stalled() == false (readable, current). 3) core.setReverting(true) for one block: stalled() returns TRUE and flagStall() succeeds (stallMark=1000, stallUnreadable=true). Expected: stalled() false and flagStall() reverts NotStalled, because the core was unreadable for one block, not 144 rounds. 4) core.setReverting(false); warp to round 1291 with core settled 1290 (healthy for a day, nobody pokes); core.setReverting(true) again for one block; void() succeeds and voided()==true. Expected: TooEarly, because the core settled every round between the two blocks. Proof test: test/scratch/StaleCursorFlag.t.sol, fails on this code at step 3.","severity":"low","snippet":"        return (ended > c + STALL_ROUNDS, c, false, true);","title":"Unreadable-core stall is measured from the walker's stale cursor, so one block of unreadability can be flagged and two blocks a day apart can void the game"}],"hash":"6708d5258f9ccb6a9b66113ffa75cd5dc09f1131b1d893afba3f6afd865778cf","nodeId":"6b9cdbe6-25e5-4776-9a33-7bf9c1b9e8e1","outcome":"completed","summary":"Review complete. The findings are in `.imd-findings.json` with one finding, its failing proof test, and eleven coverage rows.\n\n**What I reviewed.** The permissions area for `LightsOn`: the Access Control, Trust Gap and Asymmetry passes from the Pashov reference, applied to all seven state-changing entry points, the constructor, the two self-call read helpers, and the launch configuration. The baseline suite passes on this tree (109 tests, including the invariant run). No file outside `test/scratch/` and the findings file was changed.\n\n**Finding (low), `flagStall()` / `void()` at `src/LightsOn.sol:500`.** The \"core unreadable for 144 rounds\" stall guard is measured from the walker's own cursor, which only moves when someone pokes. During a quiet spell with a healthy core, nobody pokes, so after 145 rounds a single block in which the core reverts lets anyone flag a stall at once, and a second single-block revert a day later voids the game for good, although the core settled every round in between. The same applies at launch if deployment lands more than 144 rounds after the fixed start round 1000. No funds are lost, since void refunds, but the game cannot be restarted and the documented guarantee does not hold. I rated it low because an unprivileged caller cannot make the core unreadable; it takes the core's operator or an outage. The proof under `test/scratch/StaleCursorFlag.t.sol` fails on this code at the flag step.\n\n**What holds.** `bet` and `betUntil` pull only the sender's SQK and the one-bet-per-night check cannot be bypassed. `claim` pays only the stored owner and its status transitions are one-way. `poke` and `settle` cannot be gas-starved or paged into a bad state. The healthy-core sweep in my control test never flags or voids. There is no owner, initializer or upgrade surface, and the factory gains no role.\n\n**Not reached.** The site and data folders, the money-area rounding in `LightsMath`, and the live SqueekCore's pause semantics, which decide how often the trigger above can occur in practice.","treeHash":null,"usage":{"cachedInputTokens":1169076,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":42597,"runtime":"claude","turns":33,"wallClockMs":716645}},{"artifacts":[],"attempt":1,"bundleHash":"6533527318df2af63fe1633a4346c3ec67fa547d9a1d5df7c4e3bde715eb76d1","device":"fc0a1efa39657191","findings":[],"hash":"71e0f8465cb1ed7af0af5e1f41e24bb196bfc1dc5759353d4e1f046c66b630d6","nodeId":"db568053-197c-4e2e-a57b-09c5a9e58788","outcome":"completed","summary":"Launch preparation is complete. The existing constructor already supports the factory, so game contracts and rules remain unchanged.\n\nAdded six launch tests, documented the exact configuration, and recorded both audit findings—including SqueekCore’s upgrade trust—in [ADAPTATION.md](/home/imd10/.identitymd/work/a8ff8089-dd8d-44b3-b7c1-763b3da97661/db568053-197c-4e2e-a57b-09c5a9e58788/ADAPTATION.md).\n\n`forge build` passed. Offline `forge test` passed **109 tests** with the supplied seed. Actual deployment remains with the launch service.","treeHash":"de01a24fc0cf67c9774e683a036ebf8af9e60fce","usage":{"cachedInputTokens":1570048,"inputTokens":105326,"model":"gpt-6-astra","outputTokens":17351,"runtime":"codex","turns":7,"wallClockMs":829738}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"c79042525fc4a50d","findings":[{"citation":"resolved","description":"Read in full: src/LightsOn.sol (732 lines), src/LightsMath.sol, src/ISqueek.sol, test/mocks/Mocks.sol, test/LightsBase.t.sol and the three prior audit suites (test/audit_money, test/audit_time, test/audit_attacks). forge test: 103 passed, 0 failed (unit, fuzz, invariant with fail_on_revert, replay of real rounds, vectors). Every state-changing entry point was traced with concrete values: bet/betUntil/_placeBet, claim/_claim/_due, poke/_poke/_idle/_active/_close, settle/_settle/_count/_countBet/_complete/_burn, flagStall/_stall, void/asleepTooLong. Checked against the Pashov guide passes: math (weight, share telescoping, burn floor, uint96/uint128/uint32/uint8 casts, shift bound r-openStart<=63), boundaries (every external call wrapped in try via self-call with fixed CORE_GAS, no-code core, bad page shapes, void-return/false-return token), access (no owner, no setters, no proxy, no delegatecall/callcode/selfdestruct reachable in the compiled runtime; runtime 16,808 bytes; constructor touches no external contract so it deploys on an empty chain), invariants (bets are sorted by betRound; a night can only close once round C+1 or spanEnd has ended, so no bet with betRound <= lastBetRound can arrive after that night is settled; nights' lastBetRound strictly increases; bonusPot equals the sum of LOSE stakes of ROLLED nights at or after consumedBefore so the void-time bonusPot -= stake cannot underflow; pool = winStake+loseStake+bonusIn-burned is exactly what the contract holds for that night), stall/void (NeedMoreGas floor, same-kind-of-stall rule, mark monotonicity, SettleFirst). Live Sepolia (publicnode, block 12048276): SqueekCore 0x980b...3d44 is a TransparentUpgradeableProxy (impl 0x284747c4664af2203e7a90a2ee76f22b6b5e6889, admin 0x4a8ea91a43eeecb8cffc73631627a7d6f973fdbf); state() returns the 8 words ISqueek.sol declares (settledThroughRound=1002 at round 1003, paused=false); roundPage matches MockCore: a truncated page certifies through (next active round)-1 and its end position is the last record's cumulative work (roundPage(44,80,9) -> cert 54, end 4815; roundPage(44,80,16) -> cert 78, end 7692), an empty page certifies through the requested end with start==end (roundPage(990,1002,16) -> cert 1002, no records), through>settled reverts InvalidRoundPageBounds, maxRecords=0 on an active round certifies through afterRound (isIdle semantics hold), a 16-record page costs ~124k gas (< CORE_GAS 1,000,000); every active record adds work (min work in data/rounds.json is 3). SQK 0x5501...db60 is not a proxy, has no owner/pause/mint selectors, transfer returns true, burn(uint256) burns msg.sender's balance (OpenZeppelin ERC20Burnable; ERC20InsufficientBalance on a zero balance), 18 decimals, no transfer hooks. Rounds 967-1002 are quiet on-chain and the last ride was 965-966, so startRound=1000 satisfies the T5 deploy check (999 and 1000 both quiet) regardless of when the deployment lands, because the walker reads history from round 1001. Nothing in scope could not be reached.","line":35,"path":"src/LightsOn.sol","reproduction":"forge test (103 passed). cast call 0x980b4424c007caf7a1f3670b48c8eaef7ebc3d44 'roundPage(uint64,uint64,uint256)((uint64,(uint64,uint96,uint32),(uint64,uint96,uint32),(uint64,uint64,uint96,uint32,bytes32)[]))' 44 80 9 --rpc-url https://ethereum-sepolia-rpc.publicnode.com -> certifiedThroughRound 54, end.cumulativeWork 4815 (accepted by readCorePage). cast call 0x5501e1fa81be1c3f49225fa7668da0245d07db60 'burn(uint256)' 1 --from 0x...A1 -> ERC20InsufficientBalance. Expected: the live core and token satisfy the shape and ordering rules readCorePage and _burn rely on. Actual: they do; no failing input was found.","severity":"info","snippet":"    ISqueekCore public immutable CORE;","title":"Coverage: contracts read, live dependencies reached, no reproducible defect found"},{"citation":"resolved","description":"By design the game has no admin and settles only from SqueekCore. On Sepolia that address is a TransparentUpgradeableProxy whose admin (0x4a8ea91a43eeecb8cffc73631627a7d6f973fdbf) can replace the implementation at any time. The contract already defends against a reply it cannot read (revert, other shape, no code, out of gas, a page that breaks readCorePage's ordering/work rules): every read is a self-call with CORE_GAS, bets and claims never revert on it, and after 144 rounds + 24 h anyone can void, refunding open-night bets and the bonus pot. It cannot defend against a reply that is well-formed but semantically different (for example renumbered rounds or records for rounds in which the hamster did not run): such a reply would light bulbs and settle nights as if real. This is the accepted design ('settles straight from SqueekCore's rounds') and not a defect to fix in LightsOn; it is recorded so the adapter and the final panel weigh it as the one external trust the launch carries. No change is recommended.","line":150,"path":"src/LightsOn.sol","reproduction":"State: cast storage 0x980b4424c007caf7a1f3670b48c8eaef7ebc3d44 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc (impl 0x284747c4...6889) and slot 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 (admin 0x4a8ea91a...fdbf). Input: an implementation whose roundPage(c, through, 16) returns records with strictly increasing roundId and cumulativeWork and end.cumulativeWork equal to the last record's, for rounds that were quiet. Expected by the rules: quiet rounds light nothing. Actual: readCorePage accepts the page and the walker lights a bulb per record. Only the proxy admin can produce this input; no unprivileged path exists.","severity":"info","snippet":"        CORE = ISqueekCore(cfg.core);","title":"Trust assumption: SqueekCore is an upgradeable proxy; the game's correctness is bounded by what its admin keeps serving"}],"hash":"8d6dc333db75a8a3c641e78fdf41b5989a60b570326652a73d87bf24a23fe10c","nodeId":"262acf8c-5cce-45a5-9fc1-f0e1ab5aae31","outcome":"completed","summary":"The review is complete. The findings file is written and validated, no tracked file changed, and the working tree is clean apart from the ignored build output.\n\n**Result: no reproducible defect.** The game logic, its money paths and its exits held up under every pass of the Pashov checklist, and the three earlier audits' regressions all still pass. The findings file holds two info entries: a coverage record and one trust assumption.\n\n**What was read.** All three sources in full (LightsOn, LightsMath, ISqueek), the mocks, the base harness and the money, time and attack audit suites. The full suite passes with 103 tests, including the invariant runs with fail-on-revert.\n\n**What I traced with concrete values.** Every state-changing entry point and the invariants they rest on:\n- A night can only close once its blackout's second round, or its station round, has ended, so no bet can arrive for a night after that night is settled. Bets are sorted by round and night boundaries strictly increase.\n- Winner shares telescope to exactly the pool, and the pool equals what the contract holds for that night. The void-time bonus pot equals the sum of rolled losing stakes, so the subtraction on refund cannot underflow.\n- Every read of the core is a self-call with a fixed gas budget, so a revert, a wrong shape, no code, or a page breaking the ordering rules never blocks a bet, a claim or the exit. The stall flag only counts for the same kind of stall and clears when the core settles anything.\n- No owner, setter, proxy, pause or mint. The compiled runtime has no reachable DELEGATECALL, CALLCODE or SELFDESTRUCT and is 16,808 bytes. The constructor touches no external contract, so it deploys on an empty chain.\n\n**What was reached on Sepolia.** Both live addresses, with results that match the mock the tests use:\n- SqueekCore is a transparent proxy. Its state() returns the eight declared words, and roundPage certifies through next-active-minus-one on truncation, puts the last record's work in the end position, certifies an empty range through the requested end, reverts past the settled round, and costs about 124k gas for a full page.\n- SQK is a plain OpenZeppelin ERC-20 with burn(uint256) on the caller's own balance, true-returning transfers, no fees, hooks, owner or pause.\n- Rounds 967 through 1002 are quiet and the last ride was 965 to 966, so start round 1000 passes the deploy check from the time audit no matter when the deployment lands.\n\n**The one thing the adapter should carry forward.** The core's proxy admin can replace its implementation. A reply the game cannot read is handled by the stall-and-void path, but a well-formed reply with different meaning would settle nights as if real. That is the accepted design, recorded as info rather than a defect.","treeHash":null,"usage":{"cachedInputTokens":1043649,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":53314,"runtime":"claude","turns":29,"wallClockMs":862066}},{"artifacts":[],"attempt":1,"bundleHash":"58e1b079a8088b15b7d9c7ca6055cc8f604c215114d0fa771b7a6f6fb2c45d83","device":"6b47d1bf92391c22","findings":[],"hash":"e010f08e953ac4ae5a2039de70a997ce473fd2fe1fae17013e48aebe61c398e9","nodeId":"72229d57-2c06-4ce6-828a-e8f5dcf26cfe","outcome":"completed","summary":"I updated my launch test suites for the revised contract. `forge build` and the full `forge test` pass with a forced rebuild and the verifier's fuzz seed: 141 passed, 0 failed, 0 skipped. `src/` is unchanged. I only edited `test/LightsLaunchFailures.t.sol` and `test/LightsLaunchInvariant.t.sol`, and committed nothing.\n\n**What changed since my last round.** Another contributor revised `src/LightsOn.sol` and added a `readThrough` value. When a SqueekCore that can't be read is treated as stalled, the 144 rounds now count from the last round the core had settled at the last fully successful read. That point can be ahead of the walker's cursor, which was the old starting point. My suites still passed on that code, but none of them checked the new behaviour. One spot also still assumed the old rule: the invariant suite's final step, which ends the game and checks every bet can be collected, measured the stall from the cursor alone.\n\n**New failure-path tests**, all using the exact launch config (station 36, start round 1000, the Sepolia addresses):\n- **Page fails partway through a poke:** a poke where the second page can't be read records no read. A bet during the outage records nothing either, so the stall counts from the cursor, refused at 144 rounds and allowed at 145.\n- **Dead core first seen late:** if the game is first touched long after round 1000 while the core is down, the stall can be flagged at once, counted from round 1000. Any full read in the next 24 hours clears the flag.\n- **Exact boundary (fuzzed):** over any round, a core up to 100 rounds behind, and more than 16 running rounds (so one page leaves the cursor behind), the stall opens exactly at the 145th round after the last read, and not one round earlier.\n\n**Invariant suite additions:**\n- **Two new random actions:** the core's pages break while it still answers status calls, and a long run is read with a one-page budget.\n- **New checks after every call:** `readThrough` never goes back, never passes the last ended round or anything the core reported, and only moves when nothing failed, to exactly what the core has settled. A fresh flag for an unreadable core takes its mark from the larger of `readThrough` and the cursor.\n- **Final step fixed** to use the new stall rule.\n\n**Checking the checks.** I reverted each piece of the new logic in turn, rebuilding from scratch each time, and every mutant made at least one suite fail:\n- **Cursor-only measure:** caught by the fuzz test and the invariants.\n- **Recording a read even when a page failed:** caught by the mid-poke test and the invariants.\n- **Recording a read on `poke(0)`:** caught by the invariants only.\n\nOn the first pass the fuzz test missed the cursor-only mutant, so I added the running rounds that make it separate the two rules. Along the way, two passes were misleading for build reasons, not contract ones: forge's build cache sometimes skipped a source change, and a saved invariant failure was replayed on the original code. Clearing the caches and forcing rebuilds settled both, and the original contract passes every check.\n\n**No findings to report.** I read the new code looking for ways to break it and found nothing wrong, so there is no `.imd-findings.json`. A page budget can let `readThrough` run past rounds the walker hasn't processed yet. That only delays the way out, which still opens 144 rounds after the last real read. A core whose status call answers but whose pages fail can never move `readThrough`, so the game cannot be locked that way.","treeHash":"7efbcf48d98839a9b803334567731dd387a2d99c","usage":{"cachedInputTokens":1877565,"inputTokens":62,"model":"claude-opus-5-5","outputTokens":28805,"runtime":"claude","turns":33,"wallClockMs":703535}},{"artifacts":[],"attempt":1,"bundleHash":"91178641745255a578c281a36b5bb8efb4b9c088565f5c4fcf5f51f2bbccb1dc","device":"0be47287abf7c3bd","findings":[],"hash":"fba6a89d7aea2e73bf6bb664bb0a9b1fb8d0dacb99604da7dfa0afff1c340f2b","nodeId":"56c465ab-240b-4d63-9fe5-776092e6a602","outcome":"completed","summary":"Created [launch.json](/home/imd7/.identitymd/work/a8ff8089-dd8d-44b3-b7c1-763b3da97661/56c465ab-240b-4d63-9fe5-776092e6a602/launch.json) for `LightsOn` with the exact five approved constructor values. Only the manifest is changed for submission.\n\nValidation passed: manifest structure, compiled constructor ABI, `forge build`, and all 109 tests using the supplied fuzz seed.","treeHash":"d717f17671fb7a32d1528a2546fa8c5bfdfe6778","usage":{"cachedInputTokens":412672,"inputTokens":36817,"model":"gpt-6-astra","outputTokens":3246,"runtime":"codex","turns":5,"wallClockMs":209975}}],"verification":[{"checks":[{"durationMs":16963,"exitCode":0,"name":"build","output":"Compiling 42 files with Solc 0.8.26\nSolc 0.8.26 finished in 16.79s\nCompiler run successful!\n","passed":true},{"durationMs":97216,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/LightsGas.t.sol:LightsGasTest\n[PASS] test_gasBetThatSettlesANight() (gas: 1696624)\nLogs:\n  bet that also walks 1 page, counts 4 bets (its 4 units of work): 359619\n  bet that also settles the night + SQK burn: 231834\n\n[PASS] test_gasPerAction() (gas: 3779688)\nLogs:\n  bet (first bet ever, walker idle): 177241\n  bet (walker idle): 143041\n  poke, 1 page with 16 records: 173767\n  poke, 1 page that closes the night: 121829\n  settle 5 bets: 151748\n  settle 5 bets + settle the night + SQK burn: 204547\n  claim 1 winning bet: 98275\n  claim 8 bets in one tx (6 winners, 2 losers): 244858\n  bet (returning bettor, walker idle): 155205\n\n[PASS] test_gasRolloverClaims() (gas: 1335805)\nLogs:\n  claim a winner of a bonus pot: 94947\n  claim a rolled stake that a later night won (pays 0): 66642\n\n[PASS] test_gasTheWayOut() (gas: 512071)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 11.70ms (7.93ms CPU time)\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\n\nRan 7 tests for test/audit_money/MoneyFindings.t.sol:MoneyFindingsTest\n[PASS] test_F1_oldStallFlagLetsAOneBlockPauseEndTheGame() (gas: 2348545)\nLogs:\n  Alice collects: 1080.000000000000000000\n\n[PASS] test_F1b_aFlagFromAnEarlierStallDoesNotCountForALaterOne() (gas: 839944)\n[PASS] test_F1c_aFlagFromALagStallDoesNotCountForAMomentTheCoreCantBeRead() (gas: 2063305)\n[PASS] test_F2a_coreReplyThatCannotBeReadBlocksCollecting() (gas: 1384487)\n[PASS] test_F2b_coreReplyThatCannotBeReadAlsoBlocksTheVoidExit() (gas: 1267005)\n[PASS] test_F2c_coreWithNoCodeBlocksCollecting() (gas: 1220135)\n[PASS] test_F3_voidRefundsANightTheCoreAlreadyShowsEnded() (gas: 1768842)\nLogs:\n  Alice collects: 198.000000000000000000\n\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 23.93ms (11.48ms CPU time)\n\nRan 6 tests for test/LightsLaunch.t.sol:LightsLaunchTest\n[PASS] test_factoryDeploymentRuntimeMeetsLaunchFloor() (gas: 11581095)\n[PASS] test_factoryDeploysExactConfigOnEmptyChain() (gas: 3866929)\n[PASS] test_factoryHasNoOwnerAdminOrInitializationSurface() (gas: 3906621)\n[PASS] test_laterDeploymentStillWalksHistoryFrom1001() (gas: 5794463)\n[PASS] test_launchConfigSettlesAndPaysTheNextRide() (gas: 6779226)\n[PASS] test_wellFormedCoreHistoryIsAnExternalTrustAssumption() (gas: 5734110)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 34.23ms (40.78ms CPU time)\n\nRan 9 tests for test/audit_time/TimeFindings.t.sol:TimeFindingsTest\n[PASS] test_T1a_aBetThatWaitsToBeIncludedJoinsTheNextNight() (gas: 2198309)\n[PASS] test_T1b_twoBlocksOfWaitingTurnAWinIntoARefund() (gas: 1572644)\n[PASS] test_T2a_pageReplyInANewShapeBlocksCollecting() (gas: 1367180)\n[PASS] test_T2b_pageReplyInANewShapeAlsoBlocksTheExitAndNewBets() (gas: 1751829)\n[PASS] test_T3_aDayLongPauseEndsTheGameADayEarly() (gas: 1829593)\n[PASS] test_T4a_walkerAcceptsARecordWithNoWork() (gas: 766460)\n[PASS] test_T4b_walkerAcceptsAPageThatLeavesOutRunningRounds() (gas: 752583)\n[PASS] test_T5_walkerStartedDuringARideCountsTheWrongBulbs() (gas: 1954258)\nLogs:\n  bulbs counted when started at 104: 5\n\n[PASS] test_T6_returningBettorRefusedAfterALongBusySpell() (gas: 14559584)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 42.37ms (32.26ms CPU time)\n\nRan 11 tests for test/audit_money/MoneyChecks.t.sol:MoneyChecksTest\n[PASS] testFuzz_litBetGetsBackAtLeastOneTwentyFourthOfItsWeight(uint256,uint8,uint8,uint96) (runs: 256, μ: 48246, ~: 38025)\n[PASS] test_aLitBetCanGetBackOnlyAboutOneTwentyFourthOfItsStake() (gas: 8300615)\nLogs:\n  10 SQK on bulb 1, lit, gets back: 0.416676905259716602\n\n[PASS] test_betOutcomeLooksTheSameBeforeAndAfterCollecting() (gas: 1379822)\n[PASS] test_bonusPotWithNoLosersBurnsTwoPercentOfThePotOnly() (gas: 1799443)\n[PASS] test_collectOrderDoesNotMatterAndPaysOnce() (gas: 4717688)\n[PASS] test_lastMinuteBetBeforeTheBlackoutJoinsTheNextNight() (gas: 1763198)\n[PASS] test_lastTwoRoundsOfAStationNightCanOnlyBeRefundedOrLose() (gas: 14239027)\n[PASS] test_rolledStakeRidesThenIsWonThenVoidReturnsOnlyTheLaterPot() (gas: 3750534)\n[PASS] test_voidReturnsAChainOfRolledPotsToTheExactBets() (gas: 4285643)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesLose() (gas: 17831571)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesWin() (gas: 18123210)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 95.15ms (148.89ms CPU time)\n\nRan 4 tests for test/LightsReplay.t.sol:LightsReplayTest\n[PASS] test_referenceMatchesTheKnownRides() (gas: 273511)\n[PASS] test_replayEveryRealNightWithScriptedBettors() (gas: 235802409)\nLogs:\n  bets sent in a blackout round, joined the next night 24\n  nights 19 bets 210\n  refund / win / lose 25 82 103\n  winners that got back less than their stake 7\n  SQK bet 209900 burned (wei) 3847660000000000000003\n  bonus pot 478 -> 481 (SQK) 11079\n  bonus pot 539 -> 622 (SQK) 11316\n\n[PASS] test_ridesJsonAgrees() (gas: 842770)\n[PASS] test_walkerAloneMatchesReference() (gas: 2502622)\nLogs:\n  pages to walk rounds 1..780: 9\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 502.15ms (507.89ms CPU time)\n\nRan 5 tests for test/audit_attacks/AttackFindings.t.sol:AttackFindingsTest\n[PASS] test_A1_ifHeNeverRunsAgainTheBetsAndBonusPotCanNeverLeave() (gas: 1473445)\nLogs:\n  SQK still inside the game: 0.000000000000000000\n\n[PASS] test_A1b_aLongSleepThatEndsInTimeChangesNothing() (gas: 1008689)\n[PASS] test_A2_paidBackBetsOnAnAlreadyLitBulbPileUpBeforeAnyoneCanCollect() (gas: 20153128)\nLogs:\n  Alice's first collect after the blackout, gas: 561032\n\n[PASS] test_A3_aBetCanRunOutOfGasWhenTheBlackoutIsRecordedOnTheWay() (gas: 2540752)\nLogs:\n  gas the wallet estimated (round 106 not recorded yet): 151704\n  gas the same bet needs 32 s later: 330174\n  gas limit with a 50% margin: 238056\n\n[PASS] test_A4_info_anOutOfGasPageReadCountsAsAStall() (gas: 58505440)\nLogs:\n  gas of one page read on this core: 622448\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 579.29ms (408.26ms CPU time)\n\nRan 4 tests for test/LightsVectors.t.sol:LightsVectorsTest\n[PASS] test_atLeastFifteenVectorsWithTheRequiredShapes() (gas: 14386575)\n[PASS] test_contractReproducesEveryReachableVector() (gas: 213101217)\n[PASS] test_handWorkedVectors() (gas: 162026)\n[PASS] test_vectorsFileMatchesSettlementCode() (gas: 17832712)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 578.07ms (661.45ms CPU time)\n\nRan 37 tests for test/LightsOn.t.sol:LightsOnTest\n[PASS] test_anyoneClaimsMoneyGoesToOwner() (gas: 1220538)\n[PASS] test_betBeforeGenesisReverts() (gas: 42701)\n[PASS] test_betLimitsAndPull() (gas: 612561)\n[PASS] test_betNeedsAllowance() (gas: 291918)\n[PASS] test_betsDuringTheBlackoutPairJoinTheNextNight() (gas: 2998792)\n[PASS] test_blackoutPairOnTheLastStationRounds() (gas: 10273319)\n[PASS] test_bonusPotWithOnlyWinnersIsPaidOut() (gas: 2319096)\n[PASS] test_burnAndDeadBothFail() (gas: 1304132)\n[PASS] test_burnFallsBackToDead() (gas: 1157519)\n[PASS] test_claimBeforeSettlementSkips() (gas: 762186)\n[PASS] test_constructorRejectsBadConfig() (gas: 8408)\n[PASS] test_emptyNightCarriesThePotUntouched() (gas: 2545293)\n[PASS] test_falseStartIsANightThatRollsOver() (gas: 982875)\n[PASS] test_guardBandMovesALateBetToTheNextRound() (gas: 446974)\n[PASS] test_isIdle() (gas: 277504)\n[PASS] test_lateBetWeighsOnlyTheBulbsStillDark() (gas: 2484233)\n[PASS] test_marathonShortBulbGetsBackLessThanItsStake() (gas: 3497213)\n[PASS] test_nightShapeDepartureBulbsBreakBlackout() (gas: 884355)\n[PASS] test_noAdminSurface() (gas: 34414)\n[PASS] test_nobodyLostNoPotWinnersRedistribute() (gas: 2051350)\n[PASS] test_normalNightByHand() (gas: 2441013)\n[PASS] test_oneBetPerAddressPerNight() (gas: 1923741)\n[PASS] test_oneBetPerNightAcrossTheBlackoutRounds() (gas: 2388309)\n[PASS] test_pagedSettleEqualsOneShot() (gas: 11298400)\n[PASS] test_quietSpellWalkerCatchUpBeforeRefusing() (gas: 12602578)\n[PASS] test_refundedBetInANightNobodyWon() (gas: 1361238)\n[PASS] test_rolloverThenBonusPotWonNextNight() (gas: 3371870)\n[PASS] test_stallReasons() (gas: 448451)\n[PASS] test_stationEndAndNextNight() (gas: 4653255)\n[PASS] test_twoRoundsAheadAcrossABreak() (gas: 1575238)\n[PASS] test_twoRoundsAheadRule() (gas: 4534781)\n[PASS] test_voidClearsWhenTheCoreRecovers() (gas: 654125)\n[PASS] test_voidKeepsSettledNightsAndAWonPot() (gas: 2042669)\n[PASS] test_voidNeedsClosedNightsSettledFirst() (gas: 4242689)\n[PASS] test_voidRefundsTheOpenNightAndItsBonusPot() (gas: 2796834)\n[PASS] test_walkerNeverReadsPastCertified() (gas: 7596566)\n[PASS] test_walkerPagesOverFullPages() (gas: 2792495)\nSuite result: ok. 37 passed; 0 failed; 0 skipped; finished in 579.58ms (114.39ms CPU time)\n\nRan 7 tests for test/audit_time/TimeChecks.t.sol:TimeChecksTest\n[PASS] test_betAtEveryNightEdgeJoinsTheRightNight() (gas: 5228328)\n[PASS] test_betAtStationEdges() (gas: 4970307)\n[PASS] test_betsWhileTheCoreLagsLandInTheRightNights() (gas: 9245186)\n[PASS] test_realRoundsReadFourWaysGiveTheSameNights() (gas: 349286550)\n[PASS] test_roundAndGuardBandEdges() (gas: 6224344)\n[PASS] test_stallAndVoidTimingEdges() (gas: 634139)\n[PASS] test_station64UsesTheTopBit() (gas: 11655379)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 4.69s (1.03s CPU time)\n\nRan 9 tests for test/audit_attacks/AttackChecks.t.sol:AttackChecksTest\n[PASS] test_aBigNightSettlesInStepsThatFitInABlock() (gas: 212030647)\nLogs:\n  settle(400), gas: 4338763\n  settle(400) that finishes the night, gas: 2225338\n  collect 200 bets, gas: 5406053\n\n[PASS] test_aWhaleCannotBuyALitBulbOrMoveTheNight() (gas: 4219290)\n[PASS] test_flagStallCannotBeForcedByPickingTheGas() (gas: 57496373)\n[PASS] test_nobodyCanSpendSomeoneElsesAllowanceOrTakeTheirWin() (gas: 1217966)\n[PASS] test_oddArgumentsChangeNothing() (gas: 1785799)\n[PASS] test_reentryThroughTokenHooksIsRefusedOrChangesNothing() (gas: 6674317)\n[PASS] test_theBurnCannotBeDodgedByPickingTheGas() (gas: 90152006)\n[PASS] test_theLogsAloneAddUpToTheWei() (gas: 2251093)\n[PASS] test_theMostWorkOneBetOrCollectCanBeMadeToDo() (gas: 11319599)\nLogs:\n  returning bet that reads 5 pages, gas: 980222\n  collect that reads 2 pages and counts 32 units, gas: 656676\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 4.69s (725.06ms CPU time)\n\nRan 23 tests for test/LightsLaunchFailures.t.sol:LightsLaunchFailuresTest\n[PASS] testFuzz_outOfRangeBetsAreRefused(uint8,uint256) (runs: 512, μ: 53840, ~: 53758)\n[PASS] test_betAcceptsExactEdges() (gas: 375493)\n[PASS] test_betBeforeGenesisRefusedUntilTheGuardBand() (gas: 236900)\n[PASS] test_betRejectsAmountOutsideLimits() (gas: 138713)\n[PASS] test_betRejectsBulbOutsideOneToTwentyFour() (gas: 148960)\n[PASS] test_betRevertsWhenTokenReturnsFalse() (gas: 1034812)\n[PASS] test_betUntilRefusesAfterItsLastRound() (gas: 251194)\n[PASS] test_claimRevertsWhenTokenRefusesAndStaysCollectable() (gas: 1385713)\n[PASS] test_claimSkipsUnknownAndUnreadyBets() (gas: 397942)\n[PASS] test_constructorRejectsZeroAddressesAndStationOutOfRange() (gas: 4324)\n[PASS] test_flagStallRefusedWhileHealthyOrBriefOutage() (gas: 218843)\n[PASS] test_guardBandMovesTheLastSixtySecondsToTheNextRound() (gas: 23479)\n[PASS] test_isIdleRefusesUnsettledRoundsAndRoundZero() (gas: 110503)\n[PASS] test_launchedConstantsAreTheFixedLimits() (gas: 60899)\n[PASS] test_nextRideAcceptsANewBetFromTheSameWallet() (gas: 719745)\n[PASS] test_readCorePageRejectsBrokenPagesAndThePokeReadsNothing() (gas: 1017184)\n[PASS] test_reentryFromTheTokenIsRefused() (gas: 1817166)\n[PASS] test_rolledStakeIsNotCollectableUntilTheGameEnds() (gas: 639023)\n[PASS] test_secondBetInTheSameRideRefused() (gas: 368898)\n[PASS] test_stallChecksNeedEnoughGas() (gas: 33112)\n[PASS] test_voidAfterSleepNeedsClosedRidesSettledFirst() (gas: 1176433)\n[PASS] test_voidClearsAFlagWhoseStallEnded() (gas: 281651)\n[PASS] test_voidRefusedTooEarlyThenAllowedAfterADay() (gas: 679170)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 4.69s (113.94ms CPU time)\n\nRan 5 tests for test/LightsFuzz.t.sol:LightsFuzzTest\n[PASS] testFuzz_guardBand(uint32) (runs: 256, μ: 291176, ~: 290909)\n[PASS] testFuzz_pureNightConservesToTheWei(uint256,uint8,uint64,uint96,bool) (runs: 256, μ: 213616, ~: 140496)\n[PASS] testFuzz_randomNightsPagedEqualsPure(uint256) (runs: 256, μ: 56965913, ~: 56785382)\n[PASS] testFuzz_voidLeavesNothingStuck(uint256,uint8) (runs: 256, μ: 17895182, ~: 11125169)\n[PASS] test_pureRefusesAWinnerLitBeforeItsBet() (gas: 14299)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 5.16s (7.25s CPU time)\n\nRan 1 test for test/LightsLaunchInvariant.t.sol:LightsLaunchInvariantTest\n[PASS]\nLightsLaunchInvariantTest invariants:\n[PASS] invariant_betOrderAndOnePerNight\n[PASS] invariant_collectedMatchesOutcomes\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_supplyIsConserved\n[PASS] invariant_walkerAndNights\n LightsLaunchInvariantTest invariants (runs: 24, calls: 3600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LaunchHandler | badBet      | 206   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | bet         | 234   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | burnMode    | 223   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | claim       | 222   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | claimTwice  | 170   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | coreDown    | 210   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | coreFreeze  | 219   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | coreRecover | 202   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | flagStall   | 189   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | lateInRound | 213   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | poke        | 209   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | settle      | 212   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | sleep       | 207   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | step        | 239   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | stepMany    | 217   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | tryVoid     | 202   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | waitADay    | 226   | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 17 nights 7\n  burned (SQK) 352 unburned (SQK) 0\n  voided in sequence / flags / clears 0 1 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.02s (6.01s CPU time)\n\nRan 1 test for test/LightsInvariant.t.sol:LightsInvariantTest\n[PASS]\nLightsInvariantTest invariants:\n[PASS] invariant_conservation\n[PASS] invariant_everySettledNightBalances\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_noProfitFromABulbLitWithinOneRound\n[PASS] invariant_oneBetPerAddressPerNight\n LightsInvariantTest invariants (runs: 48, calls: 9600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LightsHandler | bet         | 1248  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | claim       | 1197  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | hiccup      | 1199  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | lateInRound | 1178  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | poke        | 1210  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | settle      | 1190  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | step        | 1201  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | stepMany    | 1177  | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 43 nights 19\n  paid / rolled 10 9\n  unsettled nights 0 AlreadyBet refusals 6\n  bonus pot riding (SQK) 0 burned (SQK) 1077\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 96.98s (96.97s CPU time)\n\nRan 15 test suites in 96.98s (124.67s CPU time): 133 tests passed, 0 failed, 0 skipped (133 total tests)\n","passed":true},{"durationMs":125,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"LightsOn.bet(uint8,uint256)\",\"LightsOn.betUntil(uint8,uint256,uint256)\",\"LightsOn.claim(uint256[])\",\"LightsOn.flagStall()\",\"LightsOn.poke(uint256)\",\"LightsOn.settle(uint256)\",\"LightsOn.void()\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":109,\"README.md\":118,\"RULES.md\":56,\"art/led-demo/lights-engine.js\":120,\"data/lights-vectors.json\":512,\"data/rides.json\":1331,\"data/rounds.json\":164,\"foundry.toml\":21,\"site/README.md\":172,\"site/app.js\":148,\"site/board.js\":444,\"site/cam.js\":125,\"site/chain.js\":775,\"site/config.json\":16,\"site/data/rides.json\":1,\"site/engine.js\":120,\"site/icon.svg\":1,\"site/index.html\":150,\"site/led.js\":80,\"site/live-model.js\":236,\"site/live.js\":1026,\"site/rehearsal.json\":16,\"site/replay.js\":322,\"site/sign.js\":52,\"site/sprites.js\":2,\"site/styles.css\":197,\"site/test/README.md\":247,\"site/test/anvil.test.mjs\":258,\"site/test/chain.test.mjs\":272,\"site/test/contract.smoke.test.mjs\":212,\"site/test/e2e.test.mjs\":672,\"site/test/e2e/harness.mjs\":387,\"site/test/e2e/reference.mjs\":82,\"site/test/engine.test.mjs\":272,\"site/test/fixtures/roundPage-52-80-1.hex\":1,\"site/test/fixtures/roundPage-780-842-16.hex\":1,\"site/test/fixtures/roundPage-780-842-3.hex\":1,\"site/test/fixtures/state-12040340.hex\":1,\"site/test/live.test.mjs\":555,\"site/test/smoke.test.cjs\":284,\"site/test/static.test.mjs\":51,\"site/tools/build-rides.mjs\":47,\"src/ISqueek.sol\":66,\"src/LightsMath.sol\":127,\"src/LightsOn.sol\":731,\"test/DataPath.sol\":16,\"test/LightsBase.t.sol\":206,\"test/LightsFuzz.t.sol\":233,\"test/LightsGas.t.sol\":110,\"test/LightsInvariant.t.sol\":249,\"test/LightsLaunch.t.sol\":195,\"test/LightsLaunchFailures.t.sol\":465,\"test/LightsLaunchFixture.sol\":48,\"test/LightsLaunchInvariant.t.sol\":527,\"test/LightsOn.t.sol\":860,\"test/LightsReplay.t.sol\":277,\"test/LightsVectors.t.sol\":613,\"test/audit_attacks/AttackChecks.t.sol\":446,\"test/audit_attacks/AttackFindings.t.sol\":278,\"test/audit_money/MoneyChecks.t.sol\":386,\"test/audit_money/MoneyFindings.t.sol\":246,\"test/audit_time/TimeChecks.t.sol\":292,\"test/audit_time/TimeFindings.t.sol\":357,\"test/mocks/Mocks.sol\":219},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"100ed0746fa6d7515d8fd78e84a84ab1bdc1fa0306fc0162ac1f5d77ee2d497a","verifiedTreeHash":"7fe9591a92e6b07943b867a57e7c0f3cca407d91","verifierVersion":"0.1.0+3dcb4df2"},{"checks":[{"durationMs":17595,"exitCode":0,"name":"build","output":"Compiling 40 files with Solc 0.8.26\nSolc 0.8.26 finished in 17.36s\nCompiler run successful!\n","passed":true},{"durationMs":96133,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/audit_money/MoneyFindings.t.sol:MoneyFindingsTest\n[PASS] test_F1_oldStallFlagLetsAOneBlockPauseEndTheGame() (gas: 2377209)\nLogs:\n  Alice collects: 1080.000000000000000000\n\n[PASS] test_F1b_aFlagFromAnEarlierStallDoesNotCountForALaterOne() (gas: 847320)\n[PASS] test_F1c_aFlagFromALagStallDoesNotCountForAMomentTheCoreCantBeRead() (gas: 2090536)\n[PASS] test_F2a_coreReplyThatCannotBeReadBlocksCollecting() (gas: 1408706)\n[PASS] test_F2b_coreReplyThatCannotBeReadAlsoBlocksTheVoidExit() (gas: 1274725)\n[PASS] test_F2c_coreWithNoCodeBlocksCollecting() (gas: 1248695)\n[PASS] test_F3_voidRefundsANightTheCoreAlreadyShowsEnded() (gas: 1776496)\nLogs:\n  Alice collects: 198.000000000000000000\n\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 25.73ms (19.24ms CPU time)\n\nRan 6 tests for test/LightsLaunch.t.sol:LightsLaunchTest\n[PASS] test_factoryDeploymentRuntimeMeetsLaunchFloor() (gas: 11681304)\n[PASS] test_factoryDeploysExactConfigOnEmptyChain() (gas: 3899470)\n[PASS] test_factoryHasNoOwnerAdminOrInitializationSurface() (gas: 3938868)\n[PASS] test_laterDeploymentStillWalksHistoryFrom1001() (gas: 5847206)\n[PASS] test_launchConfigSettlesAndPaysTheNextRide() (gas: 6836108)\n[PASS] test_wellFormedCoreHistoryIsAnExternalTrustAssumption() (gas: 5807418)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 48.42ms (64.29ms CPU time)\n\nRan 11 tests for test/audit_money/MoneyChecks.t.sol:MoneyChecksTest\n[PASS] testFuzz_litBetGetsBackAtLeastOneTwentyFourthOfItsWeight(uint256,uint8,uint8,uint96) (runs: 256, μ: 48838, ~: 40232)\n[PASS] test_aLitBetCanGetBackOnlyAboutOneTwentyFourthOfItsStake() (gas: 8335691)\nLogs:\n  10 SQK on bulb 1, lit, gets back: 0.416676905259716602\n\n[PASS] test_betOutcomeLooksTheSameBeforeAndAfterCollecting() (gas: 1404509)\n[PASS] test_bonusPotWithNoLosersBurnsTwoPercentOfThePotOnly() (gas: 1827570)\n[PASS] test_collectOrderDoesNotMatterAndPaysOnce() (gas: 4753144)\n[PASS] test_lastMinuteBetBeforeTheBlackoutJoinsTheNextNight() (gas: 1790981)\n[PASS] test_lastTwoRoundsOfAStationNightCanOnlyBeRefundedOrLose() (gas: 14276482)\n[PASS] test_rolledStakeRidesThenIsWonThenVoidReturnsOnlyTheLaterPot() (gas: 3772007)\n[PASS] test_voidReturnsAChainOfRolledPotsToTheExactBets() (gas: 4308085)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesLose() (gas: 17880885)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesWin() (gas: 18172524)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 84.11ms (173.19ms CPU time)\n\nRan 4 tests for test/LightsGas.t.sol:LightsGasTest\n[PASS] test_gasBetThatSettlesANight() (gas: 1724686)\nLogs:\n  bet that also walks 1 page, counts 4 bets (its 4 units of work): 362994\n  bet that also settles the night + SQK burn: 232113\n\n[PASS] test_gasPerAction() (gas: 3810540)\nLogs:\n  bet (first bet ever, walker idle): 177520\n  bet (walker idle): 143320\n  poke, 1 page with 16 records: 177142\n  poke, 1 page that closes the night: 125204\n  settle 5 bets: 151748\n  settle 5 bets + settle the night + SQK burn: 204547\n  claim 1 winning bet: 98554\n  claim 8 bets in one tx (6 winners, 2 losers): 245137\n  bet (returning bettor, walker idle): 155484\n\n[PASS] test_gasRolloverClaims() (gas: 1363588)\nLogs:\n  claim a winner of a bonus pot: 95226\n  claim a rolled stake that a later night won (pays 0): 66921\n\n[PASS] test_gasTheWayOut() (gas: 518093)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 121.82ms (10.53ms CPU time)\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\n\nRan 5 tests for test/audit_review/ReviewFindings.t.sol:ReviewFindingsTest\n[PASS] testFuzz_readThroughIsMonotone(uint16,uint8) (runs: 256, μ: 642012, ~: 512275)\n[PASS] test_aPageBudgetThatLeavesTheCursorBehindIsNotAnUnreadableStall() (gas: 3705985)\n[PASS] test_aPartialReadBetweenFlagAndVoidClearsTheFlag() (gas: 5008077)\n[PASS] test_aStateReplyWithAnUnreadablePageIsNotARead() (gas: 2172677)\n[PASS] test_pokeWithNoPagesIsNotARead() (gas: 430612)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 126.45ms (132.01ms CPU time)\n\nRan 4 tests for test/LightsVectors.t.sol:LightsVectorsTest\n[PASS] test_atLeastFifteenVectorsWithTheRequiredShapes() (gas: 14386575)\n[PASS] test_contractReproducesEveryReachableVector() (gas: 213762599)\n[PASS] test_handWorkedVectors() (gas: 162026)\n[PASS] test_vectorsFileMatchesSettlementCode() (gas: 17832712)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 488.46ms (659.22ms CPU time)\n\nRan 4 tests for test/LightsReplay.t.sol:LightsReplayTest\n[PASS] test_referenceMatchesTheKnownRides() (gas: 273511)\n[PASS] test_replayEveryRealNightWithScriptedBettors() (gas: 238575567)\nLogs:\n  bets sent in a blackout round, joined the next night 24\n  nights 19 bets 210\n  refund / win / lose 25 82 103\n  winners that got back less than their stake 7\n  SQK bet 209900 burned (wei) 3847660000000000000003\n  bonus pot 478 -> 481 (SQK) 11079\n  bonus pot 539 -> 622 (SQK) 11316\n\n[PASS] test_ridesJsonAgrees() (gas: 842770)\n[PASS] test_walkerAloneMatchesReference() (gas: 2524860)\nLogs:\n  pages to walk rounds 1..780: 9\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 629.13ms (647.61ms CPU time)\n\nRan 5 tests for test/audit_attacks/AttackFindings.t.sol:AttackFindingsTest\n[PASS] test_A1_ifHeNeverRunsAgainTheBetsAndBonusPotCanNeverLeave() (gas: 1487840)\nLogs:\n  SQK still inside the game: 0.000000000000000000\n\n[PASS] test_A1b_aLongSleepThatEndsInTimeChangesNothing() (gas: 1039424)\n[PASS] test_A2_paidBackBetsOnAnAlreadyLitBulbPileUpBeforeAnyoneCanCollect() (gas: 20211075)\nLogs:\n  Alice's first collect after the blackout, gas: 564407\n\n[PASS] test_A3_aBetCanRunOutOfGasWhenTheBlackoutIsRecordedOnTheWay() (gas: 2573444)\nLogs:\n  gas the wallet estimated (round 106 not recorded yet): 151983\n  gas the same bet needs 32 s later: 333549\n  gas limit with a 50% margin: 238474\n\n[PASS] test_A4_info_anOutOfGasPageReadCountsAsAStall() (gas: 58538953)\nLogs:\n  gas of one page read on this core: 622448\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 985.13ms (461.94ms CPU time)\n\nRan 9 tests for test/audit_time/TimeFindings.t.sol:TimeFindingsTest\n[PASS] test_T1a_aBetThatWaitsToBeIncludedJoinsTheNextNight() (gas: 2232563)\n[PASS] test_T1b_twoBlocksOfWaitingTurnAWinIntoARefund() (gas: 1600148)\n[PASS] test_T2a_pageReplyInANewShapeBlocksCollecting() (gas: 1391477)\n[PASS] test_T2b_pageReplyInANewShapeAlsoBlocksTheExitAndNewBets() (gas: 1759937)\n[PASS] test_T3_aDayLongPauseEndsTheGameADayEarly() (gas: 1840658)\n[PASS] test_T4a_walkerAcceptsARecordWithNoWork() (gas: 790478)\n[PASS] test_T4b_walkerAcceptsAPageThatLeavesOutRunningRounds() (gas: 776601)\n[PASS] test_T5_walkerStartedDuringARideCountsTheWrongBulbs() (gas: 1998997)\nLogs:\n  bulbs counted when started at 104: 5\n\n[PASS] test_T6_returningBettorRefusedAfterALongBusySpell() (gas: 14588885)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 1.81s (59.45ms CPU time)\n\nRan 37 tests for test/LightsOn.t.sol:LightsOnTest\n[PASS] test_anyoneClaimsMoneyGoesToOwner() (gas: 1244946)\n[PASS] test_betBeforeGenesisReverts() (gas: 42701)\n[PASS] test_betLimitsAndPull() (gas: 633293)\n[PASS] test_betNeedsAllowance() (gas: 312393)\n[PASS] test_betsDuringTheBlackoutPairJoinTheNextNight() (gas: 3034407)\n[PASS] test_blackoutPairOnTheLastStationRounds() (gas: 10314923)\n[PASS] test_bonusPotWithOnlyWinnersIsPaidOut() (gas: 2347942)\n[PASS] test_burnAndDeadBothFail() (gas: 1328540)\n[PASS] test_burnFallsBackToDead() (gas: 1181648)\n[PASS] test_claimBeforeSettlementSkips() (gas: 786014)\n[PASS] test_constructorRejectsBadConfig() (gas: 8408)\n[PASS] test_emptyNightCarriesThePotUntouched() (gas: 2574101)\n[PASS] test_falseStartIsANightThatRollsOver() (gas: 1007348)\n[PASS] test_guardBandMovesALateBetToTheNextRound() (gas: 467728)\n[PASS] test_isIdle() (gas: 277684)\n[PASS] test_lateBetWeighsOnlyTheBulbsStillDark() (gas: 2512901)\n[PASS] test_marathonShortBulbGetsBackLessThanItsStake() (gas: 3526997)\n[PASS] test_nightShapeDepartureBulbsBreakBlackout() (gas: 908160)\n[PASS] test_noAdminSurface() (gas: 34414)\n[PASS] test_nobodyLostNoPotWinnersRedistribute() (gas: 2076987)\n[PASS] test_normalNightByHand() (gas: 2467143)\n[PASS] test_oneBetPerAddressPerNight() (gas: 1966893)\n[PASS] test_oneBetPerNightAcrossTheBlackoutRounds() (gas: 2420316)\n[PASS] test_pagedSettleEqualsOneShot() (gas: 11338989)\n[PASS] test_quietSpellWalkerCatchUpBeforeRefusing() (gas: 12626919)\n[PASS] test_refundedBetInANightNobodyWon() (gas: 1389086)\n[PASS] test_rolloverThenBonusPotWonNextNight() (gas: 3402243)\n[PASS] test_stallReasons() (gas: 475927)\n[PASS] test_stationEndAndNextNight() (gas: 4688736)\n[PASS] test_twoRoundsAheadAcrossABreak() (gas: 1603021)\n[PASS] test_twoRoundsAheadRule() (gas: 4568712)\n[PASS] test_voidClearsWhenTheCoreRecovers() (gas: 663473)\n[PASS] test_voidKeepsSettledNightsAndAWonPot() (gas: 2058173)\n[PASS] test_voidNeedsClosedNightsSettledFirst() (gas: 4255610)\n[PASS] test_voidRefundsTheOpenNightAndItsBonusPot() (gas: 2815992)\n[PASS] test_walkerNeverReadsPastCertified() (gas: 7645723)\n[PASS] test_walkerPagesOverFullPages() (gas: 2813481)\nSuite result: ok. 37 passed; 0 failed; 0 skipped; finished in 1.81s (131.46ms CPU time)\n\nRan 9 tests for test/audit_attacks/AttackChecks.t.sol:AttackChecksTest\n[PASS] test_aBigNightSettlesInStepsThatFitInABlock() (gas: 212222137)\nLogs:\n  settle(400), gas: 4338763\n  settle(400) that finishes the night, gas: 2225338\n  collect 200 bets, gas: 5406332\n\n[PASS] test_aWhaleCannotBuyALitBulbOrMoveTheNight() (gas: 4254611)\n[PASS] test_flagStallCannotBeForcedByPickingTheGas() (gas: 57516937)\n[PASS] test_nobodyCanSpendSomeoneElsesAllowanceOrTakeTheirWin() (gas: 1242374)\n[PASS] test_oddArgumentsChangeNothing() (gas: 1811457)\n[PASS] test_reentryThroughTokenHooksIsRefusedOrChangesNothing() (gas: 6705319)\n[PASS] test_theBurnCannotBeDodgedByPickingTheGas() (gas: 90223065)\n[PASS] test_theLogsAloneAddUpToTheWei() (gas: 2283303)\n[PASS] test_theMostWorkOneBetOrCollectCanBeMadeToDo() (gas: 11350251)\nLogs:\n  returning bet that reads 5 pages, gas: 984132\n  collect that reads 2 pages and counts 32 units, gas: 657079\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 5.43s (946.09ms CPU time)\n\nRan 7 tests for test/audit_time/TimeChecks.t.sol:TimeChecksTest\n[PASS] test_betAtEveryNightEdgeJoinsTheRightNight() (gas: 5277357)\n[PASS] test_betAtStationEdges() (gas: 5005401)\n[PASS] test_betsWhileTheCoreLagsLandInTheRightNights() (gas: 9331351)\n[PASS] test_realRoundsReadFourWaysGiveTheSameNights() (gas: 354519027)\n[PASS] test_roundAndGuardBandEdges() (gas: 6245377)\n[PASS] test_stallAndVoidTimingEdges() (gas: 638272)\n[PASS] test_station64UsesTheTopBit() (gas: 11686871)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 5.52s (1.04s CPU time)\n\nRan 5 tests for test/LightsFuzz.t.sol:LightsFuzzTest\n[PASS] testFuzz_guardBand(uint32) (runs: 256, μ: 311635, ~: 311384)\n[PASS] testFuzz_pureNightConservesToTheWei(uint256,uint8,uint64,uint96,bool) (runs: 256, μ: 206037, ~: 139744)\n[PASS] testFuzz_randomNightsPagedEqualsPure(uint256) (runs: 256, μ: 57407506, ~: 57212108)\n[PASS] testFuzz_voidLeavesNothingStuck(uint256,uint8) (runs: 256, μ: 18323845, ~: 11301244)\n[PASS] test_pureRefusesAWinnerLitBeforeItsBet() (gas: 14299)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 5.52s (7.96s CPU time)\n\nRan 1 test for test/LightsInvariant.t.sol:LightsInvariantTest\n[PASS]\nLightsInvariantTest invariants:\n[PASS] invariant_conservation\n[PASS] invariant_everySettledNightBalances\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_noProfitFromABulbLitWithinOneRound\n[PASS] invariant_oneBetPerAddressPerNight\n LightsInvariantTest invariants (runs: 48, calls: 9600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LightsHandler | bet         | 1248  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | claim       | 1197  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | hiccup      | 1199  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | lateInRound | 1178  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | poke        | 1210  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | settle      | 1190  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | step        | 1201  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | stepMany    | 1177  | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 46 nights 19\n  paid / rolled 7 12\n  unsettled nights 0 AlreadyBet refusals 11\n  bonus pot riding (SQK) 0 burned (SQK) 1246\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 95.84s (95.83s CPU time)\n\nRan 14 test suites in 95.85s (118.45s CPU time): 114 tests passed, 0 failed, 0 skipped (114 total tests)\n","passed":true},{"durationMs":134,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"LightsOn.bet(uint8,uint256)\",\"LightsOn.betUntil(uint8,uint256,uint256)\",\"LightsOn.claim(uint256[])\",\"LightsOn.flagStall()\",\"LightsOn.poke(uint256)\",\"LightsOn.settle(uint256)\",\"LightsOn.void()\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":166,\"README.md\":121,\"RULES.md\":56,\"art/led-demo/lights-engine.js\":120,\"data/lights-vectors.json\":512,\"data/rides.json\":1331,\"data/rounds.json\":164,\"foundry.toml\":21,\"site/README.md\":172,\"site/app.js\":148,\"site/board.js\":444,\"site/cam.js\":125,\"site/chain.js\":775,\"site/config.json\":16,\"site/data/rides.json\":1,\"site/engine.js\":120,\"site/icon.svg\":1,\"site/index.html\":150,\"site/led.js\":80,\"site/live-model.js\":236,\"site/live.js\":1026,\"site/rehearsal.json\":16,\"site/replay.js\":322,\"site/sign.js\":52,\"site/sprites.js\":2,\"site/styles.css\":197,\"site/test/README.md\":247,\"site/test/anvil.test.mjs\":258,\"site/test/chain.test.mjs\":272,\"site/test/contract.smoke.test.mjs\":212,\"site/test/e2e.test.mjs\":672,\"site/test/e2e/harness.mjs\":387,\"site/test/e2e/reference.mjs\":82,\"site/test/engine.test.mjs\":272,\"site/test/fixtures/roundPage-52-80-1.hex\":1,\"site/test/fixtures/roundPage-780-842-16.hex\":1,\"site/test/fixtures/roundPage-780-842-3.hex\":1,\"site/test/fixtures/state-12040340.hex\":1,\"site/test/live.test.mjs\":555,\"site/test/smoke.test.cjs\":284,\"site/test/static.test.mjs\":51,\"site/tools/build-rides.mjs\":47,\"src/ISqueek.sol\":66,\"src/LightsMath.sol\":127,\"src/LightsOn.sol\":742,\"test/DataPath.sol\":16,\"test/LightsBase.t.sol\":206,\"test/LightsFuzz.t.sol\":233,\"test/LightsGas.t.sol\":110,\"test/LightsInvariant.t.sol\":249,\"test/LightsLaunch.t.sol\":195,\"test/LightsOn.t.sol\":860,\"test/LightsReplay.t.sol\":277,\"test/LightsVectors.t.sol\":613,\"test/audit_attacks/AttackChecks.t.sol\":446,\"test/audit_attacks/AttackFindings.t.sol\":278,\"test/audit_money/MoneyChecks.t.sol\":386,\"test/audit_money/MoneyFindings.t.sol\":246,\"test/audit_review/ReviewFindings.t.sol\":162,\"test/audit_time/TimeChecks.t.sol\":292,\"test/audit_time/TimeFindings.t.sol\":357,\"test/mocks/Mocks.sol\":219},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2151,"exitCode":0,"name":"slither","output":"[medium/high] incorrect-equality at src/LightsOn.sol:284: LightsOn._idle(LightsOn.Walker,uint256,uint256) (src/LightsOn.sol#284-291) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LightsOn.sol:284: LightsOn._idle(LightsOn.Walker,uint256,uint256) (src/LightsOn.sol#284-291) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LightsOn.sol:284: LightsOn._idle(LightsOn.Walker,uint256,uint256) (src/LightsOn.sol#284-291) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LightsOn.sol:189: LightsOn._placeBet(uint8,uint256) (src/LightsOn.sol#189-230) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LightsOn.sol:605: LightsOn.openNight() (src/LightsOn.sol#605-609) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LightsOn.sol:294: LightsOn._active(LightsOn.Walker,uint256) (src/LightsOn.sol#294-304) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LightsOn.sol:294: LightsOn._active(LightsOn.Walker,uint256) (src/LightsOn.sol#294-304) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LightsOn.sol:724: LightsOn._lastEndedRound() (src/LightsOn.sol#724-727) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/LightsOn.sol:234: Reentrancy in LightsOn.claim(uint256[]) (src/LightsOn.sol#234-239):\n[medium/medium] reentrancy-no-eth at src/LightsOn.sol:335: Reentrancy in LightsOn._settle(uint256) (src/LightsOn.sol#335-354):\n[medium/medium] reentrancy-no-eth at src/LightsOn.sol:189: Reentrancy in LightsOn._placeBet(uint8,uint256) (src/LightsOn.sol#189-230):\n[medium/medium] uninitialized-local at src/LightsOn.sol:373: LightsOn._count(LightsOn.Night,uint256,uint256,uint256).t (src/LightsOn.sol#373) is a local variable never initialized\n[medium/medium] uninitialized-local at src/LightsOn.sol:546: LightsOn.void().walkFirst (src/LightsOn.sol#546) is a local variable never initialized\n[medium/medium] uninitialized-local at src/LightsOn.sol:662: LightsOn._litRounds(uint256,uint64,uint256).k (src/LightsOn.sol#662) is a local variable never initialized\n[medium/medium] unused-return at src/LightsOn.sol:411: LightsOn._complete(LightsOn.Night,uint256,uint256) (src/LightsOn.sol#411-425) ignores return value by (result,burned,bonusOut,None) = LightsMath.close(night.sumW,night.winStake,night.loseStake,bonusIn,BURN_BPS) (src/LightsOn.sol#414-415)\n[medium/medium] unused-return at src/LightsOn.sol:676: LightsOn.readCoreState() (src/LightsOn.sol#676-678) ignores return value by (settledThrough,None,None,None,None,None,None,None) = CORE.state() (src/LightsOn.sol#677)\n[low/medium] calls-loop at src/LightsOn.sol:711: LightsOn._readPage(uint256,uint256) (src/LightsOn.sol#711-721) has external calls inside a loop: (c,r) = this.readCorePage{gas: CORE_GAS}(from,through) (src/LightsOn.sol#716-720)\n[low/medium] calls-loop at src/LightsOn.sol:443: LightsOn._claim(uint256) (src/LightsOn.sol#443-462) has external calls inside a loop: amount != 0 && ! SQK.transfer(owner,amount) (src/LightsOn.sol#460)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: (ok,ret) = address(SQK).call(abi.encodeCall(IERC20Min.transfer,(DEAD,amount))) (src/LightsOn.sol#431)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: (ok,ret) = address(SQK).call(abi.encodeCall(IERC20Min.transfer,(DEAD,amount))) (src/LightsOn.sol#431)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: (ok,ret) = address(SQK).call(abi.encodeCall(IERC20Min.transfer,(DEAD,amount))) (src/LightsOn.sol#431)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: SQK.burn(amount) (src/LightsOn.sol#428-438)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: SQK.burn(amount) (src/LightsOn.sol#428-438)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: SQK.burn(amount) (src/LightsOn.sol#428-438)\n[low/medium] calls-loop at src/LightsOn.sol:711: LightsOn._readPage(uint256,uint256) (src/LightsOn.sol#711-721) has external calls inside a loop: (c,r) = this.readCorePage{gas: CORE_GAS}(from,through) (src/LightsOn.sol#716-720)\n[low/medium] calls-loop at src/LightsOn.sol:711: LightsOn._readPage(uint256,uint256) (src/LightsOn.sol#711-721) has external calls inside a loop: (c,r) = this.readCorePage{gas: CORE_GAS}(from,through) (src/LightsOn.sol#716-720)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: SQK.burn(amount) (src/LightsOn.sol#428-438)\n[low/medium] calls-loop at src/LightsOn.sol:711: LightsOn._readPage(uint256,uint256) (src/LightsOn.sol#711-721) has external calls inside a loop: (c,r) = this.readCorePage{gas: CORE_GAS}(from,through) (src/LightsOn.sol#716-720)\n[low/medium] calls-loop at src/LightsOn.sol:427: LightsOn._burn(uint256) (src/LightsOn.sol#427-439) has external calls inside a loop: (ok,ret) = address(SQK).call(abi.encodeCall(IERC20Min.transfer,(DEAD,amount))) (src/LightsOn.sol#431)\n[low/medium] reentrancy-benign at src/LightsOn.sol:427: Reentrancy in LightsOn._burn(uint256) (src/LightsOn.sol#427-439):\n[low/medium] reentrancy-benign at src/LightsOn.sol:189: Reentrancy in LightsOn._placeBet(uint8,uint256) (src/LightsOn.sol#189-230):\n[low/medium] timestamp at src/LightsOn.sol:189: LightsOn._placeBet(uint8,uint256) (src/LightsOn.sol#189-230) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:443: LightsOn._claim(uint256) (src/LightsOn.sol#443-462) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:514: LightsOn.flagStall() (src/LightsOn.sol#514-524) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:498: LightsOn._stall() (src/LightsOn.sol#498-512) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:729: LightsOn._popcount(uint64) (src/LightsOn.sol#729-733) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:544: LightsOn.void() (src/LightsOn.sol#544-567) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:309: LightsOn._close(LightsOn.Walker,uint256,uint256) (src/LightsOn.sol#309-324) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:284: LightsOn._idle(LightsOn.Walker,uint256,uint256) (src/LightsOn.sol#284-291) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:724: LightsOn._lastEndedRound() (src/LightsOn.sol#724-727) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:367: LightsOn._count(LightsOn.Night,uint256,uint256,uint256) (src/LightsOn.sol#367-390) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:528: LightsOn.asleepTooLong() (src/LightsOn.sol#528-536) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:161: LightsOn.roundAt(uint256) (src/LightsOn.sol#161-163) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:605: LightsOn.openNight() (src/LightsOn.sol#605-609) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:249: LightsOn._poke(uint256) (src/LightsOn.sol#249-280) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:184: LightsOn.betUntil(uint8,uint256,uint256) (src/LightsOn.sol#184-187) uses timestamp for comparisons\n[low/medium] timestamp at src/LightsOn.sol:294: LightsOn._active(LightsOn.Walker,uint256) (src/LightsOn.sol#294-304) uses timestamp for comparisons","passed":true},{"durationMs":613,"exitCode":0,"name":"aderyn","output":"[high] unsafe-casting at src/LightsOn.sol:272: Unsafe Casting of integers (10 places)\n[low] costly-loop at src/LightsOn.sol:236: Costly operations inside loop (6 places)\n[low] internal-function-used-once at src/LightsMath.sol:33: Internal Function Used Only Once (6 places)\n[low] large-numeric-literal at src/LightsMath.sol:52: Large Numeric Literal (3 places)\n[low] literal-instead-of-constant at src/LightsOn.sol:148: Literal Instead of Constant (7 places)\n[low] require-revert-in-loop at src/LightsMath.sol:96: Loop Contains `require`/`revert` (3 places)\n[low] unchecked-return at src/LightsOn.sol:647: Unchecked Return (2 places)\n[low] uninitialized-local-variable at src/LightsOn.sol:236: Uninitialized Local Variable (2 places)\n[low] unsafe-erc20-operation at src/LightsOn.sol:431: Unsafe ERC20 Operation (2 places)\n[low] unused-public-function at src/LightsOn.sol:490: Public Function Not Used Internally","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"5b7511b097ea1b311b2285459d2adde4dd6fb52b3f7e7bb2077b6be55108d15e","verifiedTreeHash":"64b23d649ba283b4b281bc15c1afe2e9861cff28","verifierVersion":"0.1.0+3dcb4df2"},{"checks":[{"durationMs":17175,"exitCode":0,"name":"build","output":"Compiling 40 files with Solc 0.8.26\nSolc 0.8.26 finished in 16.94s\nCompiler run successful!\n","passed":true},{"durationMs":102349,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/audit_review/ReviewFindings.t.sol:ReviewFindingsTest\n[PASS] testFuzz_readThroughIsMonotone(uint16,uint8) (runs: 256, μ: 642012, ~: 512275)\n[PASS] test_aPageBudgetThatLeavesTheCursorBehindIsNotAnUnreadableStall() (gas: 3705985)\n[PASS] test_aPartialReadBetweenFlagAndVoidClearsTheFlag() (gas: 5008077)\n[PASS] test_aStateReplyWithAnUnreadablePageIsNotARead() (gas: 2172677)\n[PASS] test_pokeWithNoPagesIsNotARead() (gas: 430612)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 133.20ms (136.71ms CPU time)\n\nRan 9 tests for test/audit_attacks/AttackChecks.t.sol:AttackChecksTest\n[PASS] test_aBigNightSettlesInStepsThatFitInABlock() (gas: 212222137)\nLogs:\n  settle(400), gas: 4338763\n  settle(400) that finishes the night, gas: 2225338\n  collect 200 bets, gas: 5406332\n\n[PASS] test_aWhaleCannotBuyALitBulbOrMoveTheNight() (gas: 4254611)\n[PASS] test_flagStallCannotBeForcedByPickingTheGas() (gas: 57516937)\n[PASS] test_nobodyCanSpendSomeoneElsesAllowanceOrTakeTheirWin() (gas: 1242374)\n[PASS] test_oddArgumentsChangeNothing() (gas: 1811457)\n[PASS] test_reentryThroughTokenHooksIsRefusedOrChangesNothing() (gas: 6705319)\n[PASS] test_theBurnCannotBeDodgedByPickingTheGas() (gas: 90223065)\n[PASS] test_theLogsAloneAddUpToTheWei() (gas: 2283303)\n[PASS] test_theMostWorkOneBetOrCollectCanBeMadeToDo() (gas: 11350251)\nLogs:\n  returning bet that reads 5 pages, gas: 984132\n  collect that reads 2 pages and counts 32 units, gas: 657079\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 475.70ms (723.56ms CPU time)\n\nRan 4 tests for test/LightsVectors.t.sol:LightsVectorsTest\n[PASS] test_atLeastFifteenVectorsWithTheRequiredShapes() (gas: 14386575)\n[PASS] test_contractReproducesEveryReachableVector() (gas: 213762599)\n[PASS] test_handWorkedVectors() (gas: 162026)\n[PASS] test_vectorsFileMatchesSettlementCode() (gas: 17832712)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 573.94ms (711.88ms CPU time)\n\nRan 7 tests for test/audit_time/TimeChecks.t.sol:TimeChecksTest\n[PASS] test_betAtEveryNightEdgeJoinsTheRightNight() (gas: 5277357)\n[PASS] test_betAtStationEdges() (gas: 5005401)\n[PASS] test_betsWhileTheCoreLagsLandInTheRightNights() (gas: 9331351)\n[PASS] test_realRoundsReadFourWaysGiveTheSameNights() (gas: 354519027)\n[PASS] test_roundAndGuardBandEdges() (gas: 6245377)\n[PASS] test_stallAndVoidTimingEdges() (gas: 638272)\n[PASS] test_station64UsesTheTopBit() (gas: 11686871)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 1.02s (1.08s CPU time)\n\nRan 5 tests for test/audit_attacks/AttackFindings.t.sol:AttackFindingsTest\n[PASS] test_A1_ifHeNeverRunsAgainTheBetsAndBonusPotCanNeverLeave() (gas: 1487840)\nLogs:\n  SQK still inside the game: 0.000000000000000000\n\n[PASS] test_A1b_aLongSleepThatEndsInTimeChangesNothing() (gas: 1039424)\n[PASS] test_A2_paidBackBetsOnAnAlreadyLitBulbPileUpBeforeAnyoneCanCollect() (gas: 20211075)\nLogs:\n  Alice's first collect after the blackout, gas: 564407\n\n[PASS] test_A3_aBetCanRunOutOfGasWhenTheBlackoutIsRecordedOnTheWay() (gas: 2573444)\nLogs:\n  gas the wallet estimated (round 106 not recorded yet): 151983\n  gas the same bet needs 32 s later: 333549\n  gas limit with a 50% margin: 238474\n\n[PASS] test_A4_info_anOutOfGasPageReadCountsAsAStall() (gas: 58538953)\nLogs:\n  gas of one page read on this core: 622448\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.81s (430.47ms CPU time)\n\nRan 4 tests for test/LightsReplay.t.sol:LightsReplayTest\n[PASS] test_referenceMatchesTheKnownRides() (gas: 273511)\n[PASS] test_replayEveryRealNightWithScriptedBettors() (gas: 238575567)\nLogs:\n  bets sent in a blackout round, joined the next night 24\n  nights 19 bets 210\n  refund / win / lose 25 82 103\n  winners that got back less than their stake 7\n  SQK bet 209900 burned (wei) 3847660000000000000003\n  bonus pot 478 -> 481 (SQK) 11079\n  bonus pot 539 -> 622 (SQK) 11316\n\n[PASS] test_ridesJsonAgrees() (gas: 842770)\n[PASS] test_walkerAloneMatchesReference() (gas: 2524860)\nLogs:\n  pages to walk rounds 1..780: 9\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.23s (447.30ms CPU time)\n\nRan 6 tests for test/LightsLaunch.t.sol:LightsLaunchTest\n[PASS] test_factoryDeploymentRuntimeMeetsLaunchFloor() (gas: 11681304)\n[PASS] test_factoryDeploysExactConfigOnEmptyChain() (gas: 3899470)\n[PASS] test_factoryHasNoOwnerAdminOrInitializationSurface() (gas: 3938868)\n[PASS] test_laterDeploymentStillWalksHistoryFrom1001() (gas: 5847206)\n[PASS] test_launchConfigSettlesAndPaysTheNextRide() (gas: 6836108)\n[PASS] test_wellFormedCoreHistoryIsAnExternalTrustAssumption() (gas: 5807418)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 5.50s (52.14ms CPU time)\n\nRan 7 tests for test/audit_money/MoneyFindings.t.sol:MoneyFindingsTest\n[PASS] test_F1_oldStallFlagLetsAOneBlockPauseEndTheGame() (gas: 2377209)\nLogs:\n  Alice collects: 1080.000000000000000000\n\n[PASS] test_F1b_aFlagFromAnEarlierStallDoesNotCountForALaterOne() (gas: 847320)\n[PASS] test_F1c_aFlagFromALagStallDoesNotCountForAMomentTheCoreCantBeRead() (gas: 2090536)\n[PASS] test_F2a_coreReplyThatCannotBeReadBlocksCollecting() (gas: 1408706)\n[PASS] test_F2b_coreReplyThatCannotBeReadAlsoBlocksTheVoidExit() (gas: 1274725)\n[PASS] test_F2c_coreWithNoCodeBlocksCollecting() (gas: 1248695)\n[PASS] test_F3_voidRefundsANightTheCoreAlreadyShowsEnded() (gas: 1776496)\nLogs:\n  Alice collects: 198.000000000000000000\n\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 5.50s (13.55ms CPU time)\n\nRan 4 tests for test/LightsGas.t.sol:LightsGasTest\n[PASS] test_gasBetThatSettlesANight() (gas: 1724686)\nLogs:\n  bet that also walks 1 page, counts 4 bets (its 4 units of work): 362994\n  bet that also settles the night + SQK burn: 232113\n\n[PASS] test_gasPerAction() (gas: 3810540)\nLogs:\n  bet (first bet ever, walker idle): 177520\n  bet (walker idle): 143320\n  poke, 1 page with 16 records: 177142\n  poke, 1 page that closes the night: 125204\n  settle 5 bets: 151748\n  settle 5 bets + settle the night + SQK burn: 204547\n  claim 1 winning bet: 98554\n  claim 8 bets in one tx (6 winners, 2 losers): 245137\n  bet (returning bettor, walker idle): 155484\n\n[PASS] test_gasRolloverClaims() (gas: 1363588)\nLogs:\n  claim a winner of a bonus pot: 95226\n  claim a rolled stake that a later night won (pays 0): 66921\n\n[PASS] test_gasTheWayOut() (gas: 518093)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 5.50s (7.48ms CPU time)\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\n\nRan 9 tests for test/audit_time/TimeFindings.t.sol:TimeFindingsTest\n[PASS] test_T1a_aBetThatWaitsToBeIncludedJoinsTheNextNight() (gas: 2232563)\n[PASS] test_T1b_twoBlocksOfWaitingTurnAWinIntoARefund() (gas: 1600148)\n[PASS] test_T2a_pageReplyInANewShapeBlocksCollecting() (gas: 1391477)\n[PASS] test_T2b_pageReplyInANewShapeAlsoBlocksTheExitAndNewBets() (gas: 1759937)\n[PASS] test_T3_aDayLongPauseEndsTheGameADayEarly() (gas: 1840658)\n[PASS] test_T4a_walkerAcceptsARecordWithNoWork() (gas: 790478)\n[PASS] test_T4b_walkerAcceptsAPageThatLeavesOutRunningRounds() (gas: 776601)\n[PASS] test_T5_walkerStartedDuringARideCountsTheWrongBulbs() (gas: 1998997)\nLogs:\n  bulbs counted when started at 104: 5\n\n[PASS] test_T6_returningBettorRefusedAfterALongBusySpell() (gas: 14588885)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 5.50s (72.08ms CPU time)\n\nRan 37 tests for test/LightsOn.t.sol:LightsOnTest\n[PASS] test_anyoneClaimsMoneyGoesToOwner() (gas: 1244946)\n[PASS] test_betBeforeGenesisReverts() (gas: 42701)\n[PASS] test_betLimitsAndPull() (gas: 633293)\n[PASS] test_betNeedsAllowance() (gas: 312393)\n[PASS] test_betsDuringTheBlackoutPairJoinTheNextNight() (gas: 3034407)\n[PASS] test_blackoutPairOnTheLastStationRounds() (gas: 10314923)\n[PASS] test_bonusPotWithOnlyWinnersIsPaidOut() (gas: 2347942)\n[PASS] test_burnAndDeadBothFail() (gas: 1328540)\n[PASS] test_burnFallsBackToDead() (gas: 1181648)\n[PASS] test_claimBeforeSettlementSkips() (gas: 786014)\n[PASS] test_constructorRejectsBadConfig() (gas: 8408)\n[PASS] test_emptyNightCarriesThePotUntouched() (gas: 2574101)\n[PASS] test_falseStartIsANightThatRollsOver() (gas: 1007348)\n[PASS] test_guardBandMovesALateBetToTheNextRound() (gas: 467728)\n[PASS] test_isIdle() (gas: 277684)\n[PASS] test_lateBetWeighsOnlyTheBulbsStillDark() (gas: 2512901)\n[PASS] test_marathonShortBulbGetsBackLessThanItsStake() (gas: 3526997)\n[PASS] test_nightShapeDepartureBulbsBreakBlackout() (gas: 908160)\n[PASS] test_noAdminSurface() (gas: 34414)\n[PASS] test_nobodyLostNoPotWinnersRedistribute() (gas: 2076987)\n[PASS] test_normalNightByHand() (gas: 2467143)\n[PASS] test_oneBetPerAddressPerNight() (gas: 1966893)\n[PASS] test_oneBetPerNightAcrossTheBlackoutRounds() (gas: 2420316)\n[PASS] test_pagedSettleEqualsOneShot() (gas: 11338989)\n[PASS] test_quietSpellWalkerCatchUpBeforeRefusing() (gas: 12626919)\n[PASS] test_refundedBetInANightNobodyWon() (gas: 1389086)\n[PASS] test_rolloverThenBonusPotWonNextNight() (gas: 3402243)\n[PASS] test_stallReasons() (gas: 475927)\n[PASS] test_stationEndAndNextNight() (gas: 4688736)\n[PASS] test_twoRoundsAheadAcrossABreak() (gas: 1603021)\n[PASS] test_twoRoundsAheadRule() (gas: 4568712)\n[PASS] test_voidClearsWhenTheCoreRecovers() (gas: 663473)\n[PASS] test_voidKeepsSettledNightsAndAWonPot() (gas: 2058173)\n[PASS] test_voidNeedsClosedNightsSettledFirst() (gas: 4255610)\n[PASS] test_voidRefundsTheOpenNightAndItsBonusPot() (gas: 2815992)\n[PASS] test_walkerNeverReadsPastCertified() (gas: 7645723)\n[PASS] test_walkerPagesOverFullPages() (gas: 2813481)\nSuite result: ok. 37 passed; 0 failed; 0 skipped; finished in 5.65s (143.16ms CPU time)\n\nRan 11 tests for test/audit_money/MoneyChecks.t.sol:MoneyChecksTest\n[PASS] testFuzz_litBetGetsBackAtLeastOneTwentyFourthOfItsWeight(uint256,uint8,uint8,uint96) (runs: 256, μ: 48838, ~: 40232)\n[PASS] test_aLitBetCanGetBackOnlyAboutOneTwentyFourthOfItsStake() (gas: 8335691)\nLogs:\n  10 SQK on bulb 1, lit, gets back: 0.416676905259716602\n\n[PASS] test_betOutcomeLooksTheSameBeforeAndAfterCollecting() (gas: 1404509)\n[PASS] test_bonusPotWithNoLosersBurnsTwoPercentOfThePotOnly() (gas: 1827570)\n[PASS] test_collectOrderDoesNotMatterAndPaysOnce() (gas: 4753144)\n[PASS] test_lastMinuteBetBeforeTheBlackoutJoinsTheNextNight() (gas: 1790981)\n[PASS] test_lastTwoRoundsOfAStationNightCanOnlyBeRefundedOrLose() (gas: 14276482)\n[PASS] test_rolledStakeRidesThenIsWonThenVoidReturnsOnlyTheLaterPot() (gas: 3772007)\n[PASS] test_voidReturnsAChainOfRolledPotsToTheExactBets() (gas: 4308085)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesLose() (gas: 17880885)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesWin() (gas: 18172524)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 5.65s (5.76s CPU time)\n\nRan 5 tests for test/LightsFuzz.t.sol:LightsFuzzTest\n[PASS] testFuzz_guardBand(uint32) (runs: 256, μ: 311635, ~: 311384)\n[PASS] testFuzz_pureNightConservesToTheWei(uint256,uint8,uint64,uint96,bool) (runs: 256, μ: 206037, ~: 139744)\n[PASS] testFuzz_randomNightsPagedEqualsPure(uint256) (runs: 256, μ: 57407506, ~: 57212108)\n[PASS] testFuzz_voidLeavesNothingStuck(uint256,uint8) (runs: 256, μ: 18323845, ~: 11301244)\n[PASS] test_pureRefusesAWinnerLitBeforeItsBet() (gas: 14299)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 5.65s (8.12s CPU time)\n\nRan 1 test for test/LightsInvariant.t.sol:LightsInvariantTest\n[PASS]\nLightsInvariantTest invariants:\n[PASS] invariant_conservation\n[PASS] invariant_everySettledNightBalances\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_noProfitFromABulbLitWithinOneRound\n[PASS] invariant_oneBetPerAddressPerNight\n LightsInvariantTest invariants (runs: 48, calls: 9600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LightsHandler | bet         | 1248  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | claim       | 1197  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | hiccup      | 1199  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | lateInRound | 1178  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | poke        | 1210  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | settle      | 1190  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | step        | 1201  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | stepMany    | 1177  | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 50 nights 18\n  paid / rolled 8 10\n  unsettled nights 0 AlreadyBet refusals 10\n  bonus pot riding (SQK) 0 burned (SQK) 1330\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 102.04s (102.03s CPU time)\n\nRan 14 test suites in 102.04s (147.22s CPU time): 114 tests passed, 0 failed, 0 skipped (114 total tests)\n","passed":true},{"durationMs":319,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"LightsOn.bet(uint8,uint256)\",\"LightsOn.betUntil(uint8,uint256,uint256)\",\"LightsOn.claim(uint256[])\",\"LightsOn.flagStall()\",\"LightsOn.poke(uint256)\",\"LightsOn.settle(uint256)\",\"LightsOn.void()\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":166,\"README.md\":121,\"RULES.md\":56,\"art/led-demo/lights-engine.js\":120,\"data/lights-vectors.json\":512,\"data/rides.json\":1331,\"data/rounds.json\":164,\"foundry.toml\":21,\"launch.json\":16,\"site/README.md\":172,\"site/app.js\":148,\"site/board.js\":444,\"site/cam.js\":125,\"site/chain.js\":775,\"site/config.json\":16,\"site/data/rides.json\":1,\"site/engine.js\":120,\"site/icon.svg\":1,\"site/index.html\":150,\"site/led.js\":80,\"site/live-model.js\":236,\"site/live.js\":1026,\"site/rehearsal.json\":16,\"site/replay.js\":322,\"site/sign.js\":52,\"site/sprites.js\":2,\"site/styles.css\":197,\"site/test/README.md\":247,\"site/test/anvil.test.mjs\":258,\"site/test/chain.test.mjs\":272,\"site/test/contract.smoke.test.mjs\":212,\"site/test/e2e.test.mjs\":672,\"site/test/e2e/harness.mjs\":387,\"site/test/e2e/reference.mjs\":82,\"site/test/engine.test.mjs\":272,\"site/test/fixtures/roundPage-52-80-1.hex\":1,\"site/test/fixtures/roundPage-780-842-16.hex\":1,\"site/test/fixtures/roundPage-780-842-3.hex\":1,\"site/test/fixtures/state-12040340.hex\":1,\"site/test/live.test.mjs\":555,\"site/test/smoke.test.cjs\":284,\"site/test/static.test.mjs\":51,\"site/tools/build-rides.mjs\":47,\"src/ISqueek.sol\":66,\"src/LightsMath.sol\":127,\"src/LightsOn.sol\":742,\"test/DataPath.sol\":16,\"test/LightsBase.t.sol\":206,\"test/LightsFuzz.t.sol\":233,\"test/LightsGas.t.sol\":110,\"test/LightsInvariant.t.sol\":249,\"test/LightsLaunch.t.sol\":195,\"test/LightsOn.t.sol\":860,\"test/LightsReplay.t.sol\":277,\"test/LightsVectors.t.sol\":613,\"test/audit_attacks/AttackChecks.t.sol\":446,\"test/audit_attacks/AttackFindings.t.sol\":278,\"test/audit_money/MoneyChecks.t.sol\":386,\"test/audit_money/MoneyFindings.t.sol\":246,\"test/audit_review/ReviewFindings.t.sol\":162,\"test/audit_time/TimeChecks.t.sol\":292,\"test/audit_time/TimeFindings.t.sol\":357,\"test/mocks/Mocks.sol\":219},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"639ce3d7b6ba0216157170cc8e6c809d1dec12abaa0f451cd0af0fa28cffa110","verifiedTreeHash":"83f32e763b4e6410aba0ba2f58e21c9baeecfb14","verifierVersion":"0.1.0+3dcb4df2"},{"checks":[{"durationMs":14788,"exitCode":0,"name":"build","output":"Compiling 39 files with Solc 0.8.26\nSolc 0.8.26 finished in 14.59s\nCompiler run successful!\n","passed":true},{"durationMs":89503,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/LightsGas.t.sol:LightsGasTest\n[PASS] test_gasBetThatSettlesANight() (gas: 1696624)\nLogs:\n  bet that also walks 1 page, counts 4 bets (its 4 units of work): 359619\n  bet that also settles the night + SQK burn: 231834\n\n[PASS] test_gasPerAction() (gas: 3779688)\nLogs:\n  bet (first bet ever, walker idle): 177241\n  bet (walker idle): 143041\n  poke, 1 page with 16 records: 173767\n  poke, 1 page that closes the night: 121829\n  settle 5 bets: 151748\n  settle 5 bets + settle the night + SQK burn: 204547\n  claim 1 winning bet: 98275\n  claim 8 bets in one tx (6 winners, 2 losers): 244858\n  bet (returning bettor, walker idle): 155205\n\n[PASS] test_gasRolloverClaims() (gas: 1335805)\nLogs:\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\n  claim a winner of a bonus pot: 94947\n  claim a rolled stake that a later night won (pays 0): 66642\n\n[PASS] test_gasTheWayOut() (gas: 512071)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 10.78ms (9.99ms CPU time)\n\nRan 7 tests for test/audit_money/MoneyFindings.t.sol:MoneyFindingsTest\n[PASS] test_F1_oldStallFlagLetsAOneBlockPauseEndTheGame() (gas: 2348545)\nLogs:\n  Alice collects: 1080.000000000000000000\n\n[PASS] test_F1b_aFlagFromAnEarlierStallDoesNotCountForALaterOne() (gas: 839944)\n[PASS] test_F1c_aFlagFromALagStallDoesNotCountForAMomentTheCoreCantBeRead() (gas: 2063305)\n[PASS] test_F2a_coreReplyThatCannotBeReadBlocksCollecting() (gas: 1384487)\n[PASS] test_F2b_coreReplyThatCannotBeReadAlsoBlocksTheVoidExit() (gas: 1267005)\n[PASS] test_F2c_coreWithNoCodeBlocksCollecting() (gas: 1220135)\n[PASS] test_F3_voidRefundsANightTheCoreAlreadyShowsEnded() (gas: 1768842)\nLogs:\n  Alice collects: 198.000000000000000000\n\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 16.31ms (16.48ms CPU time)\n\nRan 6 tests for test/LightsLaunch.t.sol:LightsLaunchTest\n[PASS] test_factoryDeploymentRuntimeMeetsLaunchFloor() (gas: 11581095)\n[PASS] test_factoryDeploysExactConfigOnEmptyChain() (gas: 3866929)\n[PASS] test_factoryHasNoOwnerAdminOrInitializationSurface() (gas: 3906621)\n[PASS] test_laterDeploymentStillWalksHistoryFrom1001() (gas: 5794463)\n[PASS] test_launchConfigSettlesAndPaysTheNextRide() (gas: 6779226)\n[PASS] test_wellFormedCoreHistoryIsAnExternalTrustAssumption() (gas: 5734110)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 31.35ms (41.24ms CPU time)\n\nRan 9 tests for test/audit_time/TimeFindings.t.sol:TimeFindingsTest\n[PASS] test_T1a_aBetThatWaitsToBeIncludedJoinsTheNextNight() (gas: 2198309)\n[PASS] test_T1b_twoBlocksOfWaitingTurnAWinIntoARefund() (gas: 1572644)\n[PASS] test_T2a_pageReplyInANewShapeBlocksCollecting() (gas: 1367180)\n[PASS] test_T2b_pageReplyInANewShapeAlsoBlocksTheExitAndNewBets() (gas: 1751829)\n[PASS] test_T3_aDayLongPauseEndsTheGameADayEarly() (gas: 1829593)\n[PASS] test_T4a_walkerAcceptsARecordWithNoWork() (gas: 766460)\n[PASS] test_T4b_walkerAcceptsAPageThatLeavesOutRunningRounds() (gas: 752583)\n[PASS] test_T5_walkerStartedDuringARideCountsTheWrongBulbs() (gas: 1954258)\nLogs:\n  bulbs counted when started at 104: 5\n\n[PASS] test_T6_returningBettorRefusedAfterALongBusySpell() (gas: 14559584)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 85.35ms (35.68ms CPU time)\n\nRan 9 tests for test/audit_attacks/AttackChecks.t.sol:AttackChecksTest\n[PASS] test_aBigNightSettlesInStepsThatFitInABlock() (gas: 212030647)\nLogs:\n  settle(400), gas: 4338763\n  settle(400) that finishes the night, gas: 2225338\n  collect 200 bets, gas: 5406053\n\n[PASS] test_aWhaleCannotBuyALitBulbOrMoveTheNight() (gas: 4219290)\n[PASS] test_flagStallCannotBeForcedByPickingTheGas() (gas: 57496373)\n[PASS] test_nobodyCanSpendSomeoneElsesAllowanceOrTakeTheirWin() (gas: 1217966)\n[PASS] test_oddArgumentsChangeNothing() (gas: 1785799)\n[PASS] test_reentryThroughTokenHooksIsRefusedOrChangesNothing() (gas: 6674317)\n[PASS] test_theBurnCannotBeDodgedByPickingTheGas() (gas: 90152006)\n[PASS] test_theLogsAloneAddUpToTheWei() (gas: 2251093)\n[PASS] test_theMostWorkOneBetOrCollectCanBeMadeToDo() (gas: 11319599)\nLogs:\n  returning bet that reads 5 pages, gas: 980222\n  collect that reads 2 pages and counts 32 units, gas: 656676\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 570.11ms (800.45ms CPU time)\n\nRan 4 tests for test/LightsVectors.t.sol:LightsVectorsTest\n[PASS] test_atLeastFifteenVectorsWithTheRequiredShapes() (gas: 14386575)\n[PASS] test_contractReproducesEveryReachableVector() (gas: 213101217)\n[PASS] test_handWorkedVectors() (gas: 162026)\n[PASS] test_vectorsFileMatchesSettlementCode() (gas: 17832712)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 600.36ms (784.03ms CPU time)\n\nRan 11 tests for test/audit_money/MoneyChecks.t.sol:MoneyChecksTest\n[PASS] testFuzz_litBetGetsBackAtLeastOneTwentyFourthOfItsWeight(uint256,uint8,uint8,uint96) (runs: 256, μ: 47699, ~: 37307)\n[PASS] test_aLitBetCanGetBackOnlyAboutOneTwentyFourthOfItsStake() (gas: 8300615)\nLogs:\n  10 SQK on bulb 1, lit, gets back: 0.416676905259716602\n\n[PASS] test_betOutcomeLooksTheSameBeforeAndAfterCollecting() (gas: 1379822)\n[PASS] test_bonusPotWithNoLosersBurnsTwoPercentOfThePotOnly() (gas: 1799443)\n[PASS] test_collectOrderDoesNotMatterAndPaysOnce() (gas: 4717688)\n[PASS] test_lastMinuteBetBeforeTheBlackoutJoinsTheNextNight() (gas: 1763198)\n[PASS] test_lastTwoRoundsOfAStationNightCanOnlyBeRefundedOrLose() (gas: 14239027)\n[PASS] test_rolledStakeRidesThenIsWonThenVoidReturnsOnlyTheLaterPot() (gas: 3750534)\n[PASS] test_voidReturnsAChainOfRolledPotsToTheExactBets() (gas: 4285643)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesLose() (gas: 17831571)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesWin() (gas: 18123210)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 1.81s (129.29ms CPU time)\n\nRan 5 tests for test/audit_attacks/AttackFindings.t.sol:AttackFindingsTest\n[PASS] test_A1_ifHeNeverRunsAgainTheBetsAndBonusPotCanNeverLeave() (gas: 1473445)\nLogs:\n  SQK still inside the game: 0.000000000000000000\n\n[PASS] test_A1b_aLongSleepThatEndsInTimeChangesNothing() (gas: 1008689)\n[PASS] test_A2_paidBackBetsOnAnAlreadyLitBulbPileUpBeforeAnyoneCanCollect() (gas: 20153128)\nLogs:\n  Alice's first collect after the blackout, gas: 561032\n\n[PASS] test_A3_aBetCanRunOutOfGasWhenTheBlackoutIsRecordedOnTheWay() (gas: 2540752)\nLogs:\n  gas the wallet estimated (round 106 not recorded yet): 151704\n  gas the same bet needs 32 s later: 330174\n  gas limit with a 50% margin: 238056\n\n[PASS] test_A4_info_anOutOfGasPageReadCountsAsAStall() (gas: 58505440)\nLogs:\n  gas of one page read on this core: 622448\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.82s (436.86ms CPU time)\n\nRan 7 tests for test/audit_time/TimeChecks.t.sol:TimeChecksTest\n[PASS] test_betAtEveryNightEdgeJoinsTheRightNight() (gas: 5228328)\n[PASS] test_betAtStationEdges() (gas: 4970307)\n[PASS] test_betsWhileTheCoreLagsLandInTheRightNights() (gas: 9245186)\n[PASS] test_realRoundsReadFourWaysGiveTheSameNights() (gas: 349286550)\n[PASS] test_roundAndGuardBandEdges() (gas: 6224344)\n[PASS] test_stallAndVoidTimingEdges() (gas: 634139)\n[PASS] test_station64UsesTheTopBit() (gas: 11655379)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 5.17s (1.04s CPU time)\n\nRan 37 tests for test/LightsOn.t.sol:LightsOnTest\n[PASS] test_anyoneClaimsMoneyGoesToOwner() (gas: 1220538)\n[PASS] test_betBeforeGenesisReverts() (gas: 42701)\n[PASS] test_betLimitsAndPull() (gas: 612561)\n[PASS] test_betNeedsAllowance() (gas: 291918)\n[PASS] test_betsDuringTheBlackoutPairJoinTheNextNight() (gas: 2998792)\n[PASS] test_blackoutPairOnTheLastStationRounds() (gas: 10273319)\n[PASS] test_bonusPotWithOnlyWinnersIsPaidOut() (gas: 2319096)\n[PASS] test_burnAndDeadBothFail() (gas: 1304132)\n[PASS] test_burnFallsBackToDead() (gas: 1157519)\n[PASS] test_claimBeforeSettlementSkips() (gas: 762186)\n[PASS] test_constructorRejectsBadConfig() (gas: 8408)\n[PASS] test_emptyNightCarriesThePotUntouched() (gas: 2545293)\n[PASS] test_falseStartIsANightThatRollsOver() (gas: 982875)\n[PASS] test_guardBandMovesALateBetToTheNextRound() (gas: 446974)\n[PASS] test_isIdle() (gas: 277504)\n[PASS] test_lateBetWeighsOnlyTheBulbsStillDark() (gas: 2484233)\n[PASS] test_marathonShortBulbGetsBackLessThanItsStake() (gas: 3497213)\n[PASS] test_nightShapeDepartureBulbsBreakBlackout() (gas: 884355)\n[PASS] test_noAdminSurface() (gas: 34414)\n[PASS] test_nobodyLostNoPotWinnersRedistribute() (gas: 2051350)\n[PASS] test_normalNightByHand() (gas: 2441013)\n[PASS] test_oneBetPerAddressPerNight() (gas: 1923741)\n[PASS] test_oneBetPerNightAcrossTheBlackoutRounds() (gas: 2388309)\n[PASS] test_pagedSettleEqualsOneShot() (gas: 11298400)\n[PASS] test_quietSpellWalkerCatchUpBeforeRefusing() (gas: 12602578)\n[PASS] test_refundedBetInANightNobodyWon() (gas: 1361238)\n[PASS] test_rolloverThenBonusPotWonNextNight() (gas: 3371870)\n[PASS] test_stallReasons() (gas: 448451)\n[PASS] test_stationEndAndNextNight() (gas: 4653255)\n[PASS] test_twoRoundsAheadAcrossABreak() (gas: 1575238)\n[PASS] test_twoRoundsAheadRule() (gas: 4534781)\n[PASS] test_voidClearsWhenTheCoreRecovers() (gas: 654125)\n[PASS] test_voidKeepsSettledNightsAndAWonPot() (gas: 2042669)\n[PASS] test_voidNeedsClosedNightsSettledFirst() (gas: 4242689)\n[PASS] test_voidRefundsTheOpenNightAndItsBonusPot() (gas: 2796834)\n[PASS] test_walkerNeverReadsPastCertified() (gas: 7596566)\n[PASS] test_walkerPagesOverFullPages() (gas: 2792495)\nSuite result: ok. 37 passed; 0 failed; 0 skipped; finished in 5.18s (118.05ms CPU time)\n\nRan 5 tests for test/LightsFuzz.t.sol:LightsFuzzTest\n[PASS] testFuzz_guardBand(uint32) (runs: 256, μ: 291166, ~: 290909)\n[PASS] testFuzz_pureNightConservesToTheWei(uint256,uint8,uint64,uint96,bool) (runs: 256, μ: 211058, ~: 140076)\n[PASS] testFuzz_randomNightsPagedEqualsPure(uint256) (runs: 256, μ: 57038607, ~: 56922354)\n[PASS] testFuzz_voidLeavesNothingStuck(uint256,uint8) (runs: 256, μ: 17749238, ~: 11007447)\n[PASS] test_pureRefusesAWinnerLitBeforeItsBet() (gas: 14299)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 5.18s (7.11s CPU time)\n\nRan 4 tests for test/LightsReplay.t.sol:LightsReplayTest\n[PASS] test_referenceMatchesTheKnownRides() (gas: 273511)\n[PASS] test_replayEveryRealNightWithScriptedBettors() (gas: 235802409)\nLogs:\n  bets sent in a blackout round, joined the next night 24\n  nights 19 bets 210\n  refund / win / lose 25 82 103\n  winners that got back less than their stake 7\n  SQK bet 209900 burned (wei) 3847660000000000000003\n  bonus pot 478 -> 481 (SQK) 11079\n  bonus pot 539 -> 622 (SQK) 11316\n\n[PASS] test_ridesJsonAgrees() (gas: 842770)\n[PASS] test_walkerAloneMatchesReference() (gas: 2502622)\nLogs:\n  pages to walk rounds 1..780: 9\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 5.55s (398.72ms CPU time)\n\nRan 1 test for test/LightsInvariant.t.sol:LightsInvariantTest\n[PASS]\nLightsInvariantTest invariants:\n[PASS] invariant_conservation\n[PASS] invariant_everySettledNightBalances\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_noProfitFromABulbLitWithinOneRound\n[PASS] invariant_oneBetPerAddressPerNight\n LightsInvariantTest invariants (runs: 48, calls: 9600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LightsHandler | bet         | 1248  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | claim       | 1197  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | hiccup      | 1199  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | lateInRound | 1178  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | poke        | 1210  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | settle      | 1190  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | step        | 1201  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | stepMany    | 1177  | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 47 nights 17\n  paid / rolled 7 10\n  unsettled nights 0 AlreadyBet refusals 11\n  bonus pot riding (SQK) 0 burned (SQK) 1452\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 89.18s (89.17s CPU time)\n\nRan 13 test suites in 89.19s (115.20s CPU time): 109 tests passed, 0 failed, 0 skipped (109 total tests)\n","passed":true},{"durationMs":180,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"LightsOn.bet(uint8,uint256)\",\"LightsOn.betUntil(uint8,uint256,uint256)\",\"LightsOn.claim(uint256[])\",\"LightsOn.flagStall()\",\"LightsOn.poke(uint256)\",\"LightsOn.settle(uint256)\",\"LightsOn.void()\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":109,\"README.md\":118,\"RULES.md\":56,\"art/led-demo/lights-engine.js\":120,\"data/lights-vectors.json\":512,\"data/rides.json\":1331,\"data/rounds.json\":164,\"foundry.toml\":21,\"site/README.md\":172,\"site/app.js\":148,\"site/board.js\":444,\"site/cam.js\":125,\"site/chain.js\":775,\"site/config.json\":16,\"site/data/rides.json\":1,\"site/engine.js\":120,\"site/icon.svg\":1,\"site/index.html\":150,\"site/led.js\":80,\"site/live-model.js\":236,\"site/live.js\":1026,\"site/rehearsal.json\":16,\"site/replay.js\":322,\"site/sign.js\":52,\"site/sprites.js\":2,\"site/styles.css\":197,\"site/test/README.md\":247,\"site/test/anvil.test.mjs\":258,\"site/test/chain.test.mjs\":272,\"site/test/contract.smoke.test.mjs\":212,\"site/test/e2e.test.mjs\":672,\"site/test/e2e/harness.mjs\":387,\"site/test/e2e/reference.mjs\":82,\"site/test/engine.test.mjs\":272,\"site/test/fixtures/roundPage-52-80-1.hex\":1,\"site/test/fixtures/roundPage-780-842-16.hex\":1,\"site/test/fixtures/roundPage-780-842-3.hex\":1,\"site/test/fixtures/state-12040340.hex\":1,\"site/test/live.test.mjs\":555,\"site/test/smoke.test.cjs\":284,\"site/test/static.test.mjs\":51,\"site/tools/build-rides.mjs\":47,\"src/ISqueek.sol\":66,\"src/LightsMath.sol\":127,\"src/LightsOn.sol\":731,\"test/DataPath.sol\":16,\"test/LightsBase.t.sol\":206,\"test/LightsFuzz.t.sol\":233,\"test/LightsGas.t.sol\":110,\"test/LightsInvariant.t.sol\":249,\"test/LightsLaunch.t.sol\":195,\"test/LightsOn.t.sol\":860,\"test/LightsReplay.t.sol\":277,\"test/LightsVectors.t.sol\":613,\"test/audit_attacks/AttackChecks.t.sol\":446,\"test/audit_attacks/AttackFindings.t.sol\":278,\"test/audit_money/MoneyChecks.t.sol\":386,\"test/audit_money/MoneyFindings.t.sol\":246,\"test/audit_time/TimeChecks.t.sol\":292,\"test/audit_time/TimeFindings.t.sol\":357,\"test/mocks/Mocks.sol\":219},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"71e0f8465cb1ed7af0af5e1f41e24bb196bfc1dc5759353d4e1f046c66b630d6","verifiedTreeHash":"de01a24fc0cf67c9774e683a036ebf8af9e60fce","verifierVersion":"0.1.0+3dcb4df2"},{"checks":[{"durationMs":21782,"exitCode":0,"name":"build","output":"Compiling 43 files with Solc 0.8.26\nSolc 0.8.26 finished in 21.51s\nCompiler run successful!\n","passed":true},{"durationMs":104283,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/LightsGas.t.sol:LightsGasTest\n[PASS] test_gasBetThatSettlesANight() (gas: 1724686)\nLogs:\n  bet that also walks 1 page, counts 4 bets (its 4 units of work): 362994\n  bet that also settles the night + SQK burn: 232113\n\n[PASS] test_gasPerAction() (gas: 3810540)\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\nLogs:\n  bet (first bet ever, walker idle): 177520\n  bet (walker idle): 143320\n  poke, 1 page with 16 records: 177142\n  poke, 1 page that closes the night: 125204\n  settle 5 bets: 151748\n  settle 5 bets + settle the night + SQK burn: 204547\n  claim 1 winning bet: 98554\n  claim 8 bets in one tx (6 winners, 2 losers): 245137\n  bet (returning bettor, walker idle): 155484\n\n[PASS] test_gasRolloverClaims() (gas: 1363588)\nLogs:\n  claim a winner of a bonus pot: 95226\n  claim a rolled stake that a later night won (pays 0): 66921\n\n[PASS] test_gasTheWayOut() (gas: 518093)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 21.85ms (12.46ms CPU time)\n\nRan 5 tests for test/audit_review/ReviewFindings.t.sol:ReviewFindingsTest\n[PASS] testFuzz_readThroughIsMonotone(uint16,uint8) (runs: 256, μ: 631126, ~: 512275)\n[PASS] test_aPageBudgetThatLeavesTheCursorBehindIsNotAnUnreadableStall() (gas: 3705985)\n[PASS] test_aPartialReadBetweenFlagAndVoidClearsTheFlag() (gas: 5008077)\n[PASS] test_aStateReplyWithAnUnreadablePageIsNotARead() (gas: 2172677)\n[PASS] test_pokeWithNoPagesIsNotARead() (gas: 430612)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 148.66ms (152.22ms CPU time)\n\nRan 11 tests for test/audit_money/MoneyChecks.t.sol:MoneyChecksTest\n[PASS] testFuzz_litBetGetsBackAtLeastOneTwentyFourthOfItsWeight(uint256,uint8,uint8,uint96) (runs: 256, μ: 49555, ~: 44067)\n[PASS] test_aLitBetCanGetBackOnlyAboutOneTwentyFourthOfItsStake() (gas: 8335691)\nLogs:\n  10 SQK on bulb 1, lit, gets back: 0.416676905259716602\n\n[PASS] test_betOutcomeLooksTheSameBeforeAndAfterCollecting() (gas: 1404509)\n[PASS] test_bonusPotWithNoLosersBurnsTwoPercentOfThePotOnly() (gas: 1827570)\n[PASS] test_collectOrderDoesNotMatterAndPaysOnce() (gas: 4753144)\n[PASS] test_lastMinuteBetBeforeTheBlackoutJoinsTheNextNight() (gas: 1790981)\n[PASS] test_lastTwoRoundsOfAStationNightCanOnlyBeRefundedOrLose() (gas: 14276482)\n[PASS] test_rolledStakeRidesThenIsWonThenVoidReturnsOnlyTheLaterPot() (gas: 3772007)\n[PASS] test_voidReturnsAChainOfRolledPotsToTheExactBets() (gas: 4308085)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesLose() (gas: 17880885)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesWin() (gas: 18172524)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 150.45ms (192.06ms CPU time)\n\nRan 9 tests for test/audit_time/TimeFindings.t.sol:TimeFindingsTest\n[PASS] test_T1a_aBetThatWaitsToBeIncludedJoinsTheNextNight() (gas: 2232563)\n[PASS] test_T1b_twoBlocksOfWaitingTurnAWinIntoARefund() (gas: 1600148)\n[PASS] test_T2a_pageReplyInANewShapeBlocksCollecting() (gas: 1391477)\n[PASS] test_T2b_pageReplyInANewShapeAlsoBlocksTheExitAndNewBets() (gas: 1759937)\n[PASS] test_T3_aDayLongPauseEndsTheGameADayEarly() (gas: 1840658)\n[PASS] test_T4a_walkerAcceptsARecordWithNoWork() (gas: 790478)\n[PASS] test_T4b_walkerAcceptsAPageThatLeavesOutRunningRounds() (gas: 776601)\n[PASS] test_T5_walkerStartedDuringARideCountsTheWrongBulbs() (gas: 1998997)\nLogs:\n  bulbs counted when started at 104: 5\n\n[PASS] test_T6_returningBettorRefusedAfterALongBusySpell() (gas: 14588885)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 567.22ms (33.05ms CPU time)\n\nRan 5 tests for test/audit_attacks/AttackFindings.t.sol:AttackFindingsTest\n[PASS] test_A1_ifHeNeverRunsAgainTheBetsAndBonusPotCanNeverLeave() (gas: 1487840)\nLogs:\n  SQK still inside the game: 0.000000000000000000\n\n[PASS] test_A1b_aLongSleepThatEndsInTimeChangesNothing() (gas: 1039424)\n[PASS] test_A2_paidBackBetsOnAnAlreadyLitBulbPileUpBeforeAnyoneCanCollect() (gas: 20211075)\nLogs:\n  Alice's first collect after the blackout, gas: 564407\n\n[PASS] test_A3_aBetCanRunOutOfGasWhenTheBlackoutIsRecordedOnTheWay() (gas: 2573444)\nLogs:\n  gas the wallet estimated (round 106 not recorded yet): 151983\n  gas the same bet needs 32 s later: 333549\n  gas limit with a 50% margin: 238474\n\n[PASS] test_A4_info_anOutOfGasPageReadCountsAsAStall() (gas: 58538953)\nLogs:\n  gas of one page read on this core: 622448\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 568.42ms (575.40ms CPU time)\n\nRan 4 tests for test/LightsReplay.t.sol:LightsReplayTest\n[PASS] test_referenceMatchesTheKnownRides() (gas: 273511)\n[PASS] test_replayEveryRealNightWithScriptedBettors() (gas: 238575567)\nLogs:\n  bets sent in a blackout round, joined the next night 24\n  nights 19 bets 210\n  refund / win / lose 25 82 103\n  winners that got back less than their stake 7\n  SQK bet 209900 burned (wei) 3847660000000000000003\n  bonus pot 478 -> 481 (SQK) 11079\n  bonus pot 539 -> 622 (SQK) 11316\n\n[PASS] test_ridesJsonAgrees() (gas: 842770)\n[PASS] test_walkerAloneMatchesReference() (gas: 2524860)\nLogs:\n  pages to walk rounds 1..780: 9\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 576.10ms (589.17ms CPU time)\n\nRan 9 tests for test/audit_attacks/AttackChecks.t.sol:AttackChecksTest\n[PASS] test_aBigNightSettlesInStepsThatFitInABlock() (gas: 212222137)\nLogs:\n  settle(400), gas: 4338763\n  settle(400) that finishes the night, gas: 2225338\n  collect 200 bets, gas: 5406332\n\n[PASS] test_aWhaleCannotBuyALitBulbOrMoveTheNight() (gas: 4254611)\n[PASS] test_flagStallCannotBeForcedByPickingTheGas() (gas: 57516937)\n[PASS] test_nobodyCanSpendSomeoneElsesAllowanceOrTakeTheirWin() (gas: 1242374)\n[PASS] test_oddArgumentsChangeNothing() (gas: 1811457)\n[PASS] test_reentryThroughTokenHooksIsRefusedOrChangesNothing() (gas: 6705319)\n[PASS] test_theBurnCannotBeDodgedByPickingTheGas() (gas: 90223065)\n[PASS] test_theLogsAloneAddUpToTheWei() (gas: 2283303)\n[PASS] test_theMostWorkOneBetOrCollectCanBeMadeToDo() (gas: 11350251)\nLogs:\n  returning bet that reads 5 pages, gas: 984132\n  collect that reads 2 pages and counts 32 units, gas: 657079\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 619.87ms (999.60ms CPU time)\n\nRan 26 tests for test/LightsLaunchFailures.t.sol:LightsLaunchFailuresTest\n[PASS] testFuzz_outOfRangeBetsAreRefused(uint8,uint256) (runs: 512, μ: 53837, ~: 53758)\n[PASS] testFuzz_unreadableStallOpensAt145RoundsAfterTheLastRead(uint256,uint256,uint256) (runs: 256, μ: 2180549, ~: 2208883)\n[PASS] test_aDeadCoreSeenLateIsFlaggableButAReadWithinTheDayClearsIt() (gas: 497176)\n[PASS] test_aPageThatFailsMidPokeRecordsNoRead() (gas: 3539972)\n[PASS] test_betAcceptsExactEdges() (gas: 396158)\n[PASS] test_betBeforeGenesisRefusedUntilTheGuardBand() (gas: 237213)\n[PASS] test_betRejectsAmountOutsideLimits() (gas: 138691)\n[PASS] test_betRejectsBulbOutsideOneToTwentyFour() (gas: 148960)\n[PASS] test_betRevertsWhenTokenReturnsFalse() (gas: 1055229)\n[PASS] test_betUntilRefusesAfterItsLastRound() (gas: 271633)\n[PASS] test_claimRevertsWhenTokenRefusesAndStaysCollectable() (gas: 1392531)\n[PASS] test_claimSkipsUnknownAndUnreadyBets() (gas: 419388)\n[PASS] test_constructorRejectsZeroAddressesAndStationOutOfRange() (gas: 4346)\n[PASS] test_flagStallRefusedWhileHealthyOrBriefOutage() (gas: 219262)\n[PASS] test_guardBandMovesTheLastSixtySecondsToTheNextRound() (gas: 23501)\n[PASS] test_isIdleRefusesUnsettledRoundsAndRoundZero() (gas: 110683)\n[PASS] test_launchedConstantsAreTheFixedLimits() (gas: 60921)\n[PASS] test_nextRideAcceptsANewBetFromTheSameWallet() (gas: 743638)\n[PASS] test_readCorePageRejectsBrokenPagesAndThePokeReadsNothing() (gas: 1038659)\n[PASS] test_reentryFromTheTokenIsRefused() (gas: 1824302)\n[PASS] test_rolledStakeIsNotCollectableUntilTheGameEnds() (gas: 663195)\n[PASS] test_secondBetInTheSameRideRefused() (gas: 396546)\n[PASS] test_stallChecksNeedEnoughGas() (gas: 33134)\n[PASS] test_voidAfterSleepNeedsClosedRidesSettledFirst() (gas: 1183606)\n[PASS] test_voidClearsAFlagWhoseStallEnded() (gas: 282008)\n[PASS] test_voidRefusedTooEarlyThenAllowedAfterADay() (gas: 683075)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 1.90s (2.14s CPU time)\n\nRan 4 tests for test/LightsVectors.t.sol:LightsVectorsTest\n[PASS] test_atLeastFifteenVectorsWithTheRequiredShapes() (gas: 14386575)\n[PASS] test_contractReproducesEveryReachableVector() (gas: 213762599)\n[PASS] test_handWorkedVectors() (gas: 162026)\n[PASS] test_vectorsFileMatchesSettlementCode() (gas: 17832712)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.04s (963.61ms CPU time)\n\nRan 6 tests for test/LightsLaunch.t.sol:LightsLaunchTest\n[PASS] test_factoryDeploymentRuntimeMeetsLaunchFloor() (gas: 11681304)\n[PASS] test_factoryDeploysExactConfigOnEmptyChain() (gas: 3899470)\n[PASS] test_factoryHasNoOwnerAdminOrInitializationSurface() (gas: 3938868)\n[PASS] test_laterDeploymentStillWalksHistoryFrom1001() (gas: 5847206)\n[PASS] test_launchConfigSettlesAndPaysTheNextRide() (gas: 6836108)\n[PASS] test_wellFormedCoreHistoryIsAnExternalTrustAssumption() (gas: 5807418)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 2.31s (58.75ms CPU time)\n\nRan 37 tests for test/LightsOn.t.sol:LightsOnTest\n[PASS] test_anyoneClaimsMoneyGoesToOwner() (gas: 1244946)\n[PASS] test_betBeforeGenesisReverts() (gas: 42701)\n[PASS] test_betLimitsAndPull() (gas: 633293)\n[PASS] test_betNeedsAllowance() (gas: 312393)\n[PASS] test_betsDuringTheBlackoutPairJoinTheNextNight() (gas: 3034407)\n[PASS] test_blackoutPairOnTheLastStationRounds() (gas: 10314923)\n[PASS] test_bonusPotWithOnlyWinnersIsPaidOut() (gas: 2347942)\n[PASS] test_burnAndDeadBothFail() (gas: 1328540)\n[PASS] test_burnFallsBackToDead() (gas: 1181648)\n[PASS] test_claimBeforeSettlementSkips() (gas: 786014)\n[PASS] test_constructorRejectsBadConfig() (gas: 8408)\n[PASS] test_emptyNightCarriesThePotUntouched() (gas: 2574101)\n[PASS] test_falseStartIsANightThatRollsOver() (gas: 1007348)\n[PASS] test_guardBandMovesALateBetToTheNextRound() (gas: 467728)\n[PASS] test_isIdle() (gas: 277684)\n[PASS] test_lateBetWeighsOnlyTheBulbsStillDark() (gas: 2512901)\n[PASS] test_marathonShortBulbGetsBackLessThanItsStake() (gas: 3526997)\n[PASS] test_nightShapeDepartureBulbsBreakBlackout() (gas: 908160)\n[PASS] test_noAdminSurface() (gas: 34414)\n[PASS] test_nobodyLostNoPotWinnersRedistribute() (gas: 2076987)\n[PASS] test_normalNightByHand() (gas: 2467143)\n[PASS] test_oneBetPerAddressPerNight() (gas: 1966893)\n[PASS] test_oneBetPerNightAcrossTheBlackoutRounds() (gas: 2420316)\n[PASS] test_pagedSettleEqualsOneShot() (gas: 11338989)\n[PASS] test_quietSpellWalkerCatchUpBeforeRefusing() (gas: 12626919)\n[PASS] test_refundedBetInANightNobodyWon() (gas: 1389086)\n[PASS] test_rolloverThenBonusPotWonNextNight() (gas: 3402243)\n[PASS] test_stallReasons() (gas: 475927)\n[PASS] test_stationEndAndNextNight() (gas: 4688736)\n[PASS] test_twoRoundsAheadAcrossABreak() (gas: 1603021)\n[PASS] test_twoRoundsAheadRule() (gas: 4568712)\n[PASS] test_voidClearsWhenTheCoreRecovers() (gas: 663473)\n[PASS] test_voidKeepsSettledNightsAndAWonPot() (gas: 2058173)\n[PASS] test_voidNeedsClosedNightsSettledFirst() (gas: 4255610)\n[PASS] test_voidRefundsTheOpenNightAndItsBonusPot() (gas: 2815992)\n[PASS] test_walkerNeverReadsPastCertified() (gas: 7645723)\n[PASS] test_walkerPagesOverFullPages() (gas: 2813481)\nSuite result: ok. 37 passed; 0 failed; 0 skipped; finished in 5.73s (137.87ms CPU time)\n\nRan 7 tests for test/audit_money/MoneyFindings.t.sol:MoneyFindingsTest\n[PASS] test_F1_oldStallFlagLetsAOneBlockPauseEndTheGame() (gas: 2377209)\nLogs:\n  Alice collects: 1080.000000000000000000\n\n[PASS] test_F1b_aFlagFromAnEarlierStallDoesNotCountForALaterOne() (gas: 847320)\n[PASS] test_F1c_aFlagFromALagStallDoesNotCountForAMomentTheCoreCantBeRead() (gas: 2090536)\n[PASS] test_F2a_coreReplyThatCannotBeReadBlocksCollecting() (gas: 1408706)\n[PASS] test_F2b_coreReplyThatCannotBeReadAlsoBlocksTheVoidExit() (gas: 1274725)\n[PASS] test_F2c_coreWithNoCodeBlocksCollecting() (gas: 1248695)\n[PASS] test_F3_voidRefundsANightTheCoreAlreadyShowsEnded() (gas: 1776496)\nLogs:\n  Alice collects: 198.000000000000000000\n\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 5.78s (34.15ms CPU time)\n\nRan 7 tests for test/audit_time/TimeChecks.t.sol:TimeChecksTest\n[PASS] test_betAtEveryNightEdgeJoinsTheRightNight() (gas: 5277357)\n[PASS] test_betAtStationEdges() (gas: 5005401)\n[PASS] test_betsWhileTheCoreLagsLandInTheRightNights() (gas: 9331351)\n[PASS] test_realRoundsReadFourWaysGiveTheSameNights() (gas: 354519027)\n[PASS] test_roundAndGuardBandEdges() (gas: 6245377)\n[PASS] test_stallAndVoidTimingEdges() (gas: 638272)\n[PASS] test_station64UsesTheTopBit() (gas: 11686871)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 5.93s (1.23s CPU time)\n\nRan 5 tests for test/LightsFuzz.t.sol:LightsFuzzTest\n[PASS] testFuzz_guardBand(uint32) (runs: 256, μ: 311645, ~: 311384)\n[PASS] testFuzz_pureNightConservesToTheWei(uint256,uint8,uint64,uint96,bool) (runs: 256, μ: 206476, ~: 139661)\n[PASS] testFuzz_randomNightsPagedEqualsPure(uint256) (runs: 256, μ: 57527288, ~: 57465683)\n[PASS] testFuzz_voidLeavesNothingStuck(uint256,uint8) (runs: 256, μ: 18854353, ~: 11582960)\n[PASS] test_pureRefusesAWinnerLitBeforeItsBet() (gas: 14299)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 6.00s (10.50s CPU time)\n\nRan 1 test for test/LightsLaunchInvariant.t.sol:LightsLaunchInvariantTest\n[PASS]\nLightsLaunchInvariantTest invariants:\n[PASS] invariant_betOrderAndOnePerNight\n[PASS] invariant_collectedMatchesOutcomes\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_supplyIsConserved\n[PASS] invariant_walkerAndNights\n LightsLaunchInvariantTest invariants (runs: 24, calls: 3600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LaunchHandler | badBet      | 188   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | bet         | 170   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | burnMode    | 173   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | claim       | 188   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | claimTwice  | 203   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | coreDown    | 186   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | coreFreeze  | 170   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | coreRecover | 212   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | flagStall   | 198   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | lateInRound | 165   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | longRun     | 205   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | pageBreak   | 167   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | poke        | 213   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | settle      | 181   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | sleep       | 213   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | step        | 180   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | stepMany    | 197   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | tryVoid     | 209   | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LaunchHandler | waitADay    | 182   | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 11 nights 11\n  burned (SQK) 430 unburned (SQK) 0\n  voided in sequence / flags / clears 0 1 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.02s (6.01s CPU time)\n\nRan 1 test for test/LightsInvariant.t.sol:LightsInvariantTest\n[PASS]\nLightsInvariantTest invariants:\n[PASS] invariant_conservation\n[PASS] invariant_everySettledNightBalances\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_noProfitFromABulbLitWithinOneRound\n[PASS] invariant_oneBetPerAddressPerNight\n LightsInvariantTest invariants (runs: 48, calls: 9600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LightsHandler | bet         | 1248  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | claim       | 1197  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | hiccup      | 1199  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | lateInRound | 1178  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | poke        | 1210  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | settle      | 1190  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | step        | 1201  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | stepMany    | 1177  | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 47 nights 22\n  paid / rolled 11 11\n  unsettled nights 0 AlreadyBet refusals 8\n  bonus pot riding (SQK) 6863 burned (SQK) 788\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 103.82s (103.76s CPU time)\n\nRan 16 test suites in 103.83s (142.18s CPU time): 141 tests passed, 0 failed, 0 skipped (141 total tests)\n","passed":true},{"durationMs":148,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"LightsOn.bet(uint8,uint256)\",\"LightsOn.betUntil(uint8,uint256,uint256)\",\"LightsOn.claim(uint256[])\",\"LightsOn.flagStall()\",\"LightsOn.poke(uint256)\",\"LightsOn.settle(uint256)\",\"LightsOn.void()\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":166,\"README.md\":121,\"RULES.md\":56,\"art/led-demo/lights-engine.js\":120,\"data/lights-vectors.json\":512,\"data/rides.json\":1331,\"data/rounds.json\":164,\"foundry.toml\":21,\"site/README.md\":172,\"site/app.js\":148,\"site/board.js\":444,\"site/cam.js\":125,\"site/chain.js\":775,\"site/config.json\":16,\"site/data/rides.json\":1,\"site/engine.js\":120,\"site/icon.svg\":1,\"site/index.html\":150,\"site/led.js\":80,\"site/live-model.js\":236,\"site/live.js\":1026,\"site/rehearsal.json\":16,\"site/replay.js\":322,\"site/sign.js\":52,\"site/sprites.js\":2,\"site/styles.css\":197,\"site/test/README.md\":247,\"site/test/anvil.test.mjs\":258,\"site/test/chain.test.mjs\":272,\"site/test/contract.smoke.test.mjs\":212,\"site/test/e2e.test.mjs\":672,\"site/test/e2e/harness.mjs\":387,\"site/test/e2e/reference.mjs\":82,\"site/test/engine.test.mjs\":272,\"site/test/fixtures/roundPage-52-80-1.hex\":1,\"site/test/fixtures/roundPage-780-842-16.hex\":1,\"site/test/fixtures/roundPage-780-842-3.hex\":1,\"site/test/fixtures/state-12040340.hex\":1,\"site/test/live.test.mjs\":555,\"site/test/smoke.test.cjs\":284,\"site/test/static.test.mjs\":51,\"site/tools/build-rides.mjs\":47,\"src/ISqueek.sol\":66,\"src/LightsMath.sol\":127,\"src/LightsOn.sol\":742,\"test/DataPath.sol\":16,\"test/LightsBase.t.sol\":206,\"test/LightsFuzz.t.sol\":233,\"test/LightsGas.t.sol\":110,\"test/LightsInvariant.t.sol\":249,\"test/LightsLaunch.t.sol\":195,\"test/LightsLaunchFailures.t.sol\":559,\"test/LightsLaunchFixture.sol\":48,\"test/LightsLaunchInvariant.t.sol\":587,\"test/LightsOn.t.sol\":860,\"test/LightsReplay.t.sol\":277,\"test/LightsVectors.t.sol\":613,\"test/audit_attacks/AttackChecks.t.sol\":446,\"test/audit_attacks/AttackFindings.t.sol\":278,\"test/audit_money/MoneyChecks.t.sol\":386,\"test/audit_money/MoneyFindings.t.sol\":246,\"test/audit_review/ReviewFindings.t.sol\":162,\"test/audit_time/TimeChecks.t.sol\":292,\"test/audit_time/TimeFindings.t.sol\":357,\"test/mocks/Mocks.sol\":219},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"e010f08e953ac4ae5a2039de70a997ce473fd2fe1fae17013e48aebe61c398e9","verifiedTreeHash":"7efbcf48d98839a9b803334567731dd387a2d99c","verifierVersion":"0.1.0+3dcb4df2"},{"checks":[{"durationMs":15257,"exitCode":0,"name":"build","output":"Compiling 39 files with Solc 0.8.26\nSolc 0.8.26 finished in 15.02s\nCompiler run successful!\n","passed":true},{"durationMs":91636,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/LightsGas.t.sol:LightsGasTest\n[PASS] test_gasBetThatSettlesANight() (gas: 1696624)\nLogs:\n  bet that also walks 1 page, counts 4 bets (its 4 units of work): 359619\n  bet that also settles the night + SQK burn: 231834\n\n[PASS] test_gasPerAction() (gas: 3779688)\nLogs:\n  bet (first bet ever, walker idle): 177241\n  bet (walker idle): 143041\n  poke, 1 page with 16 records: 173767\n  poke, 1 page that closes the night: 121829\n  settle 5 bets: 151748\n  settle 5 bets + settle the night + SQK burn: 204547\n  claim 1 winning bet: 98275\n  claim 8 bets in one tx (6 winners, 2 losers): 244858\n  bet (returning bettor, walker idle): 155205\n\n[PASS] test_gasRolloverClaims() (gas: 1335805)\nLogs:\n  claim a winner of a bonus pot: 94947\n  claim a rolled stake that a later night won (pays 0): 66642\n\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\n[PASS] test_gasTheWayOut() (gas: 512071)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 36.97ms (8.47ms CPU time)\n\nRan 7 tests for test/audit_money/MoneyFindings.t.sol:MoneyFindingsTest\n[PASS] test_F1_oldStallFlagLetsAOneBlockPauseEndTheGame() (gas: 2348545)\nLogs:\n  Alice collects: 1080.000000000000000000\n\n[PASS] test_F1b_aFlagFromAnEarlierStallDoesNotCountForALaterOne() (gas: 839944)\n[PASS] test_F1c_aFlagFromALagStallDoesNotCountForAMomentTheCoreCantBeRead() (gas: 2063305)\n[PASS] test_F2a_coreReplyThatCannotBeReadBlocksCollecting() (gas: 1384487)\n[PASS] test_F2b_coreReplyThatCannotBeReadAlsoBlocksTheVoidExit() (gas: 1267005)\n[PASS] test_F2c_coreWithNoCodeBlocksCollecting() (gas: 1220135)\n[PASS] test_F3_voidRefundsANightTheCoreAlreadyShowsEnded() (gas: 1768842)\nLogs:\n  Alice collects: 198.000000000000000000\n\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 45.80ms (48.11ms CPU time)\n\nRan 11 tests for test/audit_money/MoneyChecks.t.sol:MoneyChecksTest\n[PASS] testFuzz_litBetGetsBackAtLeastOneTwentyFourthOfItsWeight(uint256,uint8,uint8,uint96) (runs: 256, μ: 47699, ~: 37307)\n[PASS] test_aLitBetCanGetBackOnlyAboutOneTwentyFourthOfItsStake() (gas: 8300615)\nLogs:\n  10 SQK on bulb 1, lit, gets back: 0.416676905259716602\n\n[PASS] test_betOutcomeLooksTheSameBeforeAndAfterCollecting() (gas: 1379822)\n[PASS] test_bonusPotWithNoLosersBurnsTwoPercentOfThePotOnly() (gas: 1799443)\n[PASS] test_collectOrderDoesNotMatterAndPaysOnce() (gas: 4717688)\n[PASS] test_lastMinuteBetBeforeTheBlackoutJoinsTheNextNight() (gas: 1763198)\n[PASS] test_lastTwoRoundsOfAStationNightCanOnlyBeRefundedOrLose() (gas: 14239027)\n[PASS] test_rolledStakeRidesThenIsWonThenVoidReturnsOnlyTheLaterPot() (gas: 3750534)\n[PASS] test_voidReturnsAChainOfRolledPotsToTheExactBets() (gas: 4285643)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesLose() (gas: 17831571)\n[PASS] test_whalesAndMinimumBetsBalanceToTheWei_whalesWin() (gas: 18123210)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 93.55ms (221.11ms CPU time)\n\nRan 37 tests for test/LightsOn.t.sol:LightsOnTest\n[PASS] test_anyoneClaimsMoneyGoesToOwner() (gas: 1220538)\n[PASS] test_betBeforeGenesisReverts() (gas: 42701)\n[PASS] test_betLimitsAndPull() (gas: 612561)\n[PASS] test_betNeedsAllowance() (gas: 291918)\n[PASS] test_betsDuringTheBlackoutPairJoinTheNextNight() (gas: 2998792)\n[PASS] test_blackoutPairOnTheLastStationRounds() (gas: 10273319)\n[PASS] test_bonusPotWithOnlyWinnersIsPaidOut() (gas: 2319096)\n[PASS] test_burnAndDeadBothFail() (gas: 1304132)\n[PASS] test_burnFallsBackToDead() (gas: 1157519)\n[PASS] test_claimBeforeSettlementSkips() (gas: 762186)\n[PASS] test_constructorRejectsBadConfig() (gas: 8408)\n[PASS] test_emptyNightCarriesThePotUntouched() (gas: 2545293)\n[PASS] test_falseStartIsANightThatRollsOver() (gas: 982875)\n[PASS] test_guardBandMovesALateBetToTheNextRound() (gas: 446974)\n[PASS] test_isIdle() (gas: 277504)\n[PASS] test_lateBetWeighsOnlyTheBulbsStillDark() (gas: 2484233)\n[PASS] test_marathonShortBulbGetsBackLessThanItsStake() (gas: 3497213)\n[PASS] test_nightShapeDepartureBulbsBreakBlackout() (gas: 884355)\n[PASS] test_noAdminSurface() (gas: 34414)\n[PASS] test_nobodyLostNoPotWinnersRedistribute() (gas: 2051350)\n[PASS] test_normalNightByHand() (gas: 2441013)\n[PASS] test_oneBetPerAddressPerNight() (gas: 1923741)\n[PASS] test_oneBetPerNightAcrossTheBlackoutRounds() (gas: 2388309)\n[PASS] test_pagedSettleEqualsOneShot() (gas: 11298400)\n[PASS] test_quietSpellWalkerCatchUpBeforeRefusing() (gas: 12602578)\n[PASS] test_refundedBetInANightNobodyWon() (gas: 1361238)\n[PASS] test_rolloverThenBonusPotWonNextNight() (gas: 3371870)\n[PASS] test_stallReasons() (gas: 448451)\n[PASS] test_stationEndAndNextNight() (gas: 4653255)\n[PASS] test_twoRoundsAheadAcrossABreak() (gas: 1575238)\n[PASS] test_twoRoundsAheadRule() (gas: 4534781)\n[PASS] test_voidClearsWhenTheCoreRecovers() (gas: 654125)\n[PASS] test_voidKeepsSettledNightsAndAWonPot() (gas: 2042669)\n[PASS] test_voidNeedsClosedNightsSettledFirst() (gas: 4242689)\n[PASS] test_voidRefundsTheOpenNightAndItsBonusPot() (gas: 2796834)\n[PASS] test_walkerNeverReadsPastCertified() (gas: 7596566)\n[PASS] test_walkerPagesOverFullPages() (gas: 2792495)\nSuite result: ok. 37 passed; 0 failed; 0 skipped; finished in 115.56ms (175.32ms CPU time)\n\nRan 9 tests for test/audit_time/TimeFindings.t.sol:TimeFindingsTest\n[PASS] test_T1a_aBetThatWaitsToBeIncludedJoinsTheNextNight() (gas: 2198309)\n[PASS] test_T1b_twoBlocksOfWaitingTurnAWinIntoARefund() (gas: 1572644)\n[PASS] test_T2a_pageReplyInANewShapeBlocksCollecting() (gas: 1367180)\n[PASS] test_T2b_pageReplyInANewShapeAlsoBlocksTheExitAndNewBets() (gas: 1751829)\n[PASS] test_T3_aDayLongPauseEndsTheGameADayEarly() (gas: 1829593)\n[PASS] test_T4a_walkerAcceptsARecordWithNoWork() (gas: 766460)\n[PASS] test_T4b_walkerAcceptsAPageThatLeavesOutRunningRounds() (gas: 752583)\n[PASS] test_T5_walkerStartedDuringARideCountsTheWrongBulbs() (gas: 1954258)\nLogs:\n  bulbs counted when started at 104: 5\n\n[PASS] test_T6_returningBettorRefusedAfterALongBusySpell() (gas: 14559584)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 128.73ms (55.79ms CPU time)\n\nRan 6 tests for test/LightsLaunch.t.sol:LightsLaunchTest\n[PASS] test_factoryDeploymentRuntimeMeetsLaunchFloor() (gas: 11581095)\n[PASS] test_factoryDeploysExactConfigOnEmptyChain() (gas: 3866929)\n[PASS] test_factoryHasNoOwnerAdminOrInitializationSurface() (gas: 3906621)\n[PASS] test_laterDeploymentStillWalksHistoryFrom1001() (gas: 5794463)\n[PASS] test_launchConfigSettlesAndPaysTheNextRide() (gas: 6779226)\n[PASS] test_wellFormedCoreHistoryIsAnExternalTrustAssumption() (gas: 5734110)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 209.78ms (220.50ms CPU time)\n\nRan 7 tests for test/audit_time/TimeChecks.t.sol:TimeChecksTest\n[PASS] test_betAtEveryNightEdgeJoinsTheRightNight() (gas: 5228328)\n[PASS] test_betAtStationEdges() (gas: 4970307)\n[PASS] test_betsWhileTheCoreLagsLandInTheRightNights() (gas: 9245186)\n[PASS] test_realRoundsReadFourWaysGiveTheSameNights() (gas: 349286550)\n[PASS] test_roundAndGuardBandEdges() (gas: 6224344)\n[PASS] test_stallAndVoidTimingEdges() (gas: 634139)\n[PASS] test_station64UsesTheTopBit() (gas: 11655379)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 1.20s (1.26s CPU time)\n\nRan 9 tests for test/audit_attacks/AttackChecks.t.sol:AttackChecksTest\n[PASS] test_aBigNightSettlesInStepsThatFitInABlock() (gas: 212030647)\nLogs:\n  settle(400), gas: 4338763\n  settle(400) that finishes the night, gas: 2225338\n  collect 200 bets, gas: 5406053\n\n[PASS] test_aWhaleCannotBuyALitBulbOrMoveTheNight() (gas: 4219290)\n[PASS] test_flagStallCannotBeForcedByPickingTheGas() (gas: 57496373)\n[PASS] test_nobodyCanSpendSomeoneElsesAllowanceOrTakeTheirWin() (gas: 1217966)\n[PASS] test_oddArgumentsChangeNothing() (gas: 1785799)\n[PASS] test_reentryThroughTokenHooksIsRefusedOrChangesNothing() (gas: 6674317)\n[PASS] test_theBurnCannotBeDodgedByPickingTheGas() (gas: 90152006)\n[PASS] test_theLogsAloneAddUpToTheWei() (gas: 2251093)\n[PASS] test_theMostWorkOneBetOrCollectCanBeMadeToDo() (gas: 11319599)\nLogs:\n  returning bet that reads 5 pages, gas: 980222\n  collect that reads 2 pages and counts 32 units, gas: 656676\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 1.20s (712.88ms CPU time)\n\nRan 4 tests for test/LightsVectors.t.sol:LightsVectorsTest\n[PASS] test_atLeastFifteenVectorsWithTheRequiredShapes() (gas: 14386575)\n[PASS] test_contractReproducesEveryReachableVector() (gas: 213101217)\n[PASS] test_handWorkedVectors() (gas: 162026)\n[PASS] test_vectorsFileMatchesSettlementCode() (gas: 17832712)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 5.63s (824.71ms CPU time)\n\nRan 5 tests for test/audit_attacks/AttackFindings.t.sol:AttackFindingsTest\n[PASS] test_A1_ifHeNeverRunsAgainTheBetsAndBonusPotCanNeverLeave() (gas: 1473445)\nLogs:\n  SQK still inside the game: 0.000000000000000000\n\n[PASS] test_A1b_aLongSleepThatEndsInTimeChangesNothing() (gas: 1008689)\n[PASS] test_A2_paidBackBetsOnAnAlreadyLitBulbPileUpBeforeAnyoneCanCollect() (gas: 20153128)\nLogs:\n  Alice's first collect after the blackout, gas: 561032\n\n[PASS] test_A3_aBetCanRunOutOfGasWhenTheBlackoutIsRecordedOnTheWay() (gas: 2540752)\nLogs:\n  gas the wallet estimated (round 106 not recorded yet): 151704\n  gas the same bet needs 32 s later: 330174\n  gas limit with a 50% margin: 238056\n\n[PASS] test_A4_info_anOutOfGasPageReadCountsAsAStall() (gas: 58505440)\nLogs:\n  gas of one page read on this core: 622448\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 5.63s (619.38ms CPU time)\n\nRan 5 tests for test/LightsFuzz.t.sol:LightsFuzzTest\n[PASS] testFuzz_guardBand(uint32) (runs: 256, μ: 291166, ~: 290909)\n[PASS] testFuzz_pureNightConservesToTheWei(uint256,uint8,uint64,uint96,bool) (runs: 256, μ: 211058, ~: 140076)\n[PASS] testFuzz_randomNightsPagedEqualsPure(uint256) (runs: 256, μ: 57038607, ~: 56922354)\n[PASS] testFuzz_voidLeavesNothingStuck(uint256,uint8) (runs: 256, μ: 17749238, ~: 11007447)\n[PASS] test_pureRefusesAWinnerLitBeforeItsBet() (gas: 14299)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 5.65s (9.83s CPU time)\n\nRan 4 tests for test/LightsReplay.t.sol:LightsReplayTest\n[PASS] test_referenceMatchesTheKnownRides() (gas: 273511)\n[PASS] test_replayEveryRealNightWithScriptedBettors() (gas: 235802409)\nLogs:\n  bets sent in a blackout round, joined the next night 24\n  nights 19 bets 210\n  refund / win / lose 25 82 103\n  winners that got back less than their stake 7\n  SQK bet 209900 burned (wei) 3847660000000000000003\n  bonus pot 478 -> 481 (SQK) 11079\n  bonus pot 539 -> 622 (SQK) 11316\n\n[PASS] test_ridesJsonAgrees() (gas: 842770)\n[PASS] test_walkerAloneMatchesReference() (gas: 2502622)\nLogs:\n  pages to walk rounds 1..780: 9\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 5.96s (357.14ms CPU time)\n\nRan 1 test for test/LightsInvariant.t.sol:LightsInvariantTest\n[PASS]\nLightsInvariantTest invariants:\n[PASS] invariant_conservation\n[PASS] invariant_everySettledNightBalances\n[PASS] invariant_holdsExactlyWhatItOwes\n[PASS] invariant_noProfitFromABulbLitWithinOneRound\n[PASS] invariant_oneBetPerAddressPerNight\n LightsInvariantTest invariants (runs: 48, calls: 9600, reverts: 0)\n\n╭---------------+-------------+-------+---------+----------╮\n| Contract      | Selector    | Calls | Reverts | Discards |\n+==========================================================+\n| LightsHandler | bet         | 1248  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | claim       | 1197  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | hiccup      | 1199  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | lateInRound | 1178  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | poke        | 1210  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | settle      | 1190  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | step        | 1201  | 0       | 0        |\n|---------------+-------------+-------+---------+----------|\n| LightsHandler | stepMany    | 1177  | 0       | 0        |\n╰---------------+-------------+-------+---------+----------╯\n\nLogs:\n  bets 45 nights 20\n  paid / rolled 6 14\n  unsettled nights 0 AlreadyBet refusals 12\n  bonus pot riding (SQK) 0 burned (SQK) 1395\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 91.22s (91.20s CPU time)\n\nRan 13 test suites in 91.23s (117.12s CPU time): 109 tests passed, 0 failed, 0 skipped (109 total tests)\n","passed":true},{"durationMs":140,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"LightsOn.bet(uint8,uint256)\",\"LightsOn.betUntil(uint8,uint256,uint256)\",\"LightsOn.claim(uint256[])\",\"LightsOn.flagStall()\",\"LightsOn.poke(uint256)\",\"LightsOn.settle(uint256)\",\"LightsOn.void()\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":109,\"README.md\":118,\"RULES.md\":56,\"art/led-demo/lights-engine.js\":120,\"data/lights-vectors.json\":512,\"data/rides.json\":1331,\"data/rounds.json\":164,\"foundry.toml\":21,\"launch.json\":16,\"site/README.md\":172,\"site/app.js\":148,\"site/board.js\":444,\"site/cam.js\":125,\"site/chain.js\":775,\"site/config.json\":16,\"site/data/rides.json\":1,\"site/engine.js\":120,\"site/icon.svg\":1,\"site/index.html\":150,\"site/led.js\":80,\"site/live-model.js\":236,\"site/live.js\":1026,\"site/rehearsal.json\":16,\"site/replay.js\":322,\"site/sign.js\":52,\"site/sprites.js\":2,\"site/styles.css\":197,\"site/test/README.md\":247,\"site/test/anvil.test.mjs\":258,\"site/test/chain.test.mjs\":272,\"site/test/contract.smoke.test.mjs\":212,\"site/test/e2e.test.mjs\":672,\"site/test/e2e/harness.mjs\":387,\"site/test/e2e/reference.mjs\":82,\"site/test/engine.test.mjs\":272,\"site/test/fixtures/roundPage-52-80-1.hex\":1,\"site/test/fixtures/roundPage-780-842-16.hex\":1,\"site/test/fixtures/roundPage-780-842-3.hex\":1,\"site/test/fixtures/state-12040340.hex\":1,\"site/test/live.test.mjs\":555,\"site/test/smoke.test.cjs\":284,\"site/test/static.test.mjs\":51,\"site/tools/build-rides.mjs\":47,\"src/ISqueek.sol\":66,\"src/LightsMath.sol\":127,\"src/LightsOn.sol\":731,\"test/DataPath.sol\":16,\"test/LightsBase.t.sol\":206,\"test/LightsFuzz.t.sol\":233,\"test/LightsGas.t.sol\":110,\"test/LightsInvariant.t.sol\":249,\"test/LightsLaunch.t.sol\":195,\"test/LightsOn.t.sol\":860,\"test/LightsReplay.t.sol\":277,\"test/LightsVectors.t.sol\":613,\"test/audit_attacks/AttackChecks.t.sol\":446,\"test/audit_attacks/AttackFindings.t.sol\":278,\"test/audit_money/MoneyChecks.t.sol\":386,\"test/audit_money/MoneyFindings.t.sol\":246,\"test/audit_time/TimeChecks.t.sol\":292,\"test/audit_time/TimeFindings.t.sol\":357,\"test/mocks/Mocks.sol\":219},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"fba6a89d7aea2e73bf6bb664bb0a9b1fb8d0dacb99604da7dfa0afff1c340f2b","verifiedTreeHash":"d717f17671fb7a32d1528a2546fa8c5bfdfe6778","verifierVersion":"0.1.0+3dcb4df2"}]}