{"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":"13140792-b1a6-4db9-b76c-61cfbc5cfe80","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"f8a0e15e3266fc53e2704ae3aa08fe2b871eed72f941065bee9434c42e538b7a","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"893664d8c088224149a05419c5aeabcc91277fa429288d0ac72074d295b9b85f","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"4083327bc84cc3f054beb8c5c67b9cae444cd26700fb80add047e52f78593370","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"c193bf4559e16cde56147114630d7adfa7da05b4909673aa88a3666d7a6a66cf","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","tools":[]},"key":"audit_imported_code","kind":"code","role":"review","skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","state":"accepted"},{"acceptedSubmissionHash":"daafade608f3c0e289cf79973c9399fcb82c08f92674631a9817684efa036a95","dependsOn":["adapt_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"6b497bf6b1052c4eafe3e0c8b31eb2aa83a34cbd8f04052fb30ea1837c9744b3","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"3969e67ff9e4a1eeecb47e4a28356fbd94c873196df7dcc23c71c7faa9bca1f2","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"94de2a823fd09f60c7f64e03a015e0f58a6f103225ed5e5937ffc9056a70c9ee","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"9ce19b60fb0b959a769b007fbf46fecc46ffa2bb4025e5cb8cd7b8149b9c1f2f","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","state":"accepted"}],"objective":"Continue from the delivered OG Club repo (OGClubBox, OGClubFurniture; 148 tests pass at db10d56cf9cc02264ccf6ab1845df3ee330f1d6b). The game drops lootboxes: NFT furniture will only be won in raffles paid with points earned by staking OG. Retire OGClubBox and its tests, keep OGClubFurniture, src/libraries/BlockHeader.sol and MockOG, and add the three contracts below. Update the deploy script, launch.json and the README; forge build, forge test and forge fmt --check must pass. Do not deploy.\n \n## 1. OGClubStaking(token, vault, owner, pointsPerTokenDay)\n- stake(amount): credit the balance actually received, so a fee-on-transfer token cannot inflate stakes.\n- unstake(amount): any time, no lock; 1% (UNSTAKE_FEE_BPS = 100, rounded up so tiny unstakes cannot avoid it) goes to the immutable vault, the rest to the staker.\n- Points accrue on chain, continuously, at pointsPerTokenDay (immutable, 18-decimal fixed point) per whole staked token per day; pointsOf(account) includes pending accrual. Points are not transferable; the owner can never create, move or remove points or touch stakes. No pause.\n- spendPoints(account, amount): authorized spenders only. Spenders follow the furniture's minter rules: first grant immediate, later grants are 7-day proposals that lapse 7 days after maturity, revoke immediate.\n- Keep per-account state in as few storage slots as practical (EIP-8037 makes new slots costly).\n \n## 2. OGClubRaffle(staking, furniture, owner, raffleNotice)\n- createRaffle(opensAt, closesAt, pools): owner; each pool is a rarity tier {tier (uint8, display), ticketPrice in points, maxTicketsPerWallet (0 = no cap), prizes: list of {itemId, quantity}}, holding one or several items; at most 32 pools and 128 prize lines; opensAt >= now + raffleNotice (immutable, at most 30 days; 7 days on mainnet, 0 on testnets); immutable once created; cancelRaffle only before opensAt.\n- enter(raffleId, pool, tickets): during [opensAt, closesAt); spends tickets * ticketPrice points via staking; enforces the wallet cap; records a contiguous ticket range. Tickets are not tokens and cannot be transferred.\n- commitDraw(raffleId): anyone, after closesAt; sets a target block TARGET_DELAY ahead. draw(raffleId, header): anyone; verifies the header against blockhash(target) with BlockHeader and stores its prevRandao as the seed. If nobody draws within 256 blocks, commitDraw may set a new target; document the bias this allows.\n- Winners: prize count = sum of a pool's quantities; exactly min(prize count, tickets sold) distinct tickets win, chosen uniformly from the seed by a permutation of ticket indices (e.g. Feistel with cycle walking); a ticket wins at most once, a wallet may win several. Win k gets the item at position q(k) of the prize list expanded by quantity, q a second seed-derived permutation, so each winner's item and any unawarded items are random. Expose winningTicket(raffleId, pool, k) and prizeOf(raffleId, pool, k).\n- claim(raffleId, pool, wins): anyone; each win names k and the entry holding winningTicket(k); verifies it, marks k in a bitmap, mints prizeOf(k) to the entry's wallet via furniture.mintBatch. Gas grows with wins claimed, not with entrants or tickets. claimTo(raffleId, pool, wins, to): the entry's wallet only, for contract wallets. Unwon prizes are never minted.\n \n## 3. OGClubFarmVault(token, owner)\nHolds the unstake fees and pays rarity-farming seasons by Merkle root (OpenZeppelin MerkleProof, double-hashed leaf of abi.encode(seasonId, account, amount)).\n- proposeSeason(root, total): owner; total at most 50% of the unreserved balance, reserved at once; claims open 3 days later; at least 7 days between proposals; cancelSeason only before claims open.\n- claim(seasonId, account, amount, proof): pays once. After 90 days the owner can release unclaimed amounts back to the pool.\n- The owner has no other way to move tokens.\n \n## 4. Also\n- OGClubFurniture: a minter proposal lapses unless activated within 7 days after its delay ends.\n- script/encode_header.py: encode blockAccessListHash then slotNumber after requestsHash (verified on Sepolia), still refuse other unknown fields; add real Sepolia block 11921684 with its published hash as a fixture, tested for keccak and for draw.\n \n## Tests\n- Accrual exactness and boundaries; fee rounding; a fee-on-transfer mock; spender lifecycle with lapse.\n- Raffle notice, window and caps at exact boundaries; header checks and re-target after 256 blocks; permutation is a bijection (fuzz small sizes); exactly min(prize count, tickets) winners; a multi-item pool mints each item exactly its quantity when fully claimed; wrong k, wrong entry and double claims revert; anyone can claim for a winner.\n- Vault delay, 50% cap, interval, cancel, proofs, release after 90 days.\n- Invariants: staking balance == total staked; points only appear by accrual and leave by spending; vault balance >= reserved.\n- README gas table under EIP-8037: first stake, unstake, enter, draw, claim of 1 and 10 wins to a fresh wallet.\n \n## Deployment\nlaunch.json is a Sepolia test deployment: MockOG, furniture, vault, staking, raffle; raffle granted as minter and spender; raffleNotice 0. README for mainnet: existing OG token, fresh deployer, OWNER a Safe, RAFFLE_NOTICE=604800.","parentJobId":null,"planHash":"adf76e5e7a2a66d72596a2f1ae4e221ae544e202c2f80a586cb21cba8fdedee7","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"13140792-b1a6-4db9-b76c-61cfbc5cfe80","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2177-continue-delivered-og-club"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51323","feedbackHash":"c4abe7c945332691d2162e8bba33753377278a448f453f26f9fc911412f9eee5","nodeKey":"adapt_contract_project","submissionHash":"f8a0e15e3266fc53e2704ae3aa08fe2b871eed72f941065bee9434c42e538b7a","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51514","feedbackHash":"c6cf80ce9faa35ff8bb6190128a07580c21788488ebb46b90353055fc5b7ee75","nodeKey":"audit_economics","submissionHash":"893664d8c088224149a05419c5aeabcc91277fa429288d0ac72074d295b9b85f","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52419","feedbackHash":"e9fd757d68c68f8ccf70c306d0420c47009f5fcb153303bcea7a4eba57bcbe28","nodeKey":"audit_flow","submissionHash":"4083327bc84cc3f054beb8c5c67b9cae444cd26700fb80add047e52f78593370","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"53909","feedbackHash":"f5c00fb08ec03230b4489b8d57fdde19a88ab3de0622fd87d9d9b6359d59cec5","nodeKey":"audit_imported_code","submissionHash":"c193bf4559e16cde56147114630d7adfa7da05b4909673aa88a3666d7a6a66cf","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52210","feedbackHash":"7d4dd0f53a7c1963cdec46856413e463b062c10fc04d0b7be35008d51eed1d5a","nodeKey":"audit_judge","submissionHash":"daafade608f3c0e289cf79973c9399fcb82c08f92674631a9817684efa036a95","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51877","feedbackHash":"bfeafa7ca5e38f07bbed1b1ea5defd481577b35783fe329fa8bb94a7c86db603","nodeKey":"audit_math","submissionHash":"6b497bf6b1052c4eafe3e0c8b31eb2aa83a34cbd8f04052fb30ea1837c9744b3","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51451","feedbackHash":"13cf0545523e77f2a25cb93faa774fa8172cdbe85a64a75d4bebff275d539221","nodeKey":"audit_permissions","submissionHash":"3969e67ff9e4a1eeecb47e4a28356fbd94c873196df7dcc23c71c7faa9bca1f2","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51422","feedbackHash":"450a7060a81820d570254b6243acdc685081546b5f2b4c411e21ed1960974e77","nodeKey":"manifest","submissionHash":"94de2a823fd09f60c7f64e03a015e0f58a6f103225ed5e5937ffc9056a70c9ee","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50984","feedbackHash":"c636fe1b620f80db124000f3309843720e469d4744dff554c98e1f215402b7b8","nodeKey":"write_foundry_tests","submissionHash":"9ce19b60fb0b959a769b007fbf46fecc46ffa2bb4025e5cb8cd7b8149b9c1f2f","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"d5ea74209c54f9f1f875e00e211eb24ab6c88aef7e6a5576b57b60d4ab394a80","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"79373c79d1351eba","findings":[{"citation":"resolved","description":"Access x asymmetry seam. claim() may be called by anyone and always mints to the entry wallet (_claim with redirect == address(0)), while claimTo() is restricted to the entry wallet and exists so contract wallets can choose a destination. The two paths are not reconciled: the entry wallet has no way to opt out of permissionless delivery. For an entry wallet that is a contract implementing onERC1155BatchReceived (so the mint succeeds) but with no outbound ERC-1155 transfer path (a generic receiver, a module-less contract, a vault keyed to a different asset), a stranger's claim() front-runs or pre-empts the wallet's claimTo() and the prize is permanently stuck in that contract. The win bit is then set, so claimTo() reverts AlreadyClaimed. The README notes claimTo 'lets contract wallets redirect prizes', but only rejecting receivers are protected; accepting-but-immobile receivers are not. This follows the brief's 'claim: anyone' wording, so it is reported as a design gap for the author to decide, not a permission bypass. A minimal preserving fix: in _claim with redirect == 0, skip (or revert for) entries whose wallet has code and has not opted in, or let an entry wallet set a redirect once via claimTo semantics that take precedence over later permissionless claims.","line":252,"path":"src/OGClubRaffle.sol","reproduction":"State: raffle 1, pool 0, one prize (item 7), entry 0 belongs to contract W which returns the ERC-1155 magic values but exposes no safeTransferFrom-calling function. After draw: (1) stranger calls claim(1, 0, [{k:0, entry:0}]) -> succeeds, furniture.balanceOf(W, 7) == 1. (2) W calls claimTo(1, 0, [{k:0, entry:0}], alice) -> reverts AlreadyClaimed. Expected: W, the only party entitled to the prize, chooses its destination (or at least cannot be forced to receive at an address it cannot move from). Actual: the prize is locked in W. Verified in test/scratch/Probe.t.sol::test_StrangerClaimPreemptsClaimToOfAcceptingContractWallet (passes against current code, demonstrating the behavior).","severity":"low","snippet":"    function claim(uint256 raffleId, uint256 poolId, Win[] calldata wins) external nonReentrant {\n        _claim(raffleId, poolId, wins, address(0));\n    }","title":"Permissionless claim() overrides a contract wallet's claimTo() destination; prizes can be delivered to a receiver that accepts but cannot forward ERC-1155"},{"citation":"resolved","description":"These are intentional powers, not bypasses; the README (lines 177-181 and 218-220) acknowledges them. Listed so the judge has the concrete actor/sequence for each. (a) Vault self-allocation: the owner chooses root and recipients, so the unstake-fee pool can be routed to the owner at up to floor(unreserved/2) every 7 days with a 3-day delay; there is no recipient restriction. (b) Any authorized spender can burn any account's points: OGClubStaking.spendPoints(account, amount) is gated only by spenders[msg.sender]; a later grantSpender(EOA) activates after 7 days (anyone may activate in the 7-day window) and that EOA can then zero every staker's points. (c) Any authorized minter mints arbitrary ids/quantities outside raffles (OGClubFurniture.mintBatch), diluting raffle prizes. (d) revokeMinter(raffle) after a draw blocks prize delivery indefinitely while entrants' points stay spent; revokeSpender(raffle) during an open window blocks further entries. (e) renounceOwnership() on every contract is immediate (OZ Ownable2Step does not two-step renunciation): if called before the raffle's roles are granted, the system can never be made operational; after, no new raffles, seasons or role changes are possible. (f) The per-pool wallet cap is per msg.sender and trivially split across wallets, so it is a UX limit, not an economic one. No code change is required for these unless the author wants tighter bounds; any such change alters the agreed design.","line":56,"path":"src/OGClubFarmVault.sol","reproduction":"(a) owner: proposeSeason(rootOf[(1, owner, floor((vault.balance - reserved)/2))], thatTotal); warp +3 days; anyone: claim(1, owner, thatTotal, []) -> owner receives half the unreserved fee pool; repeat every 7 days. (b) owner: grantSpender(eoa); warp +7 days; anyone: activateSpender(eoa); eoa: spendPoints(victim, staking.pointsOf(victim)) -> victim's points are zero with no stake change. (d) after draw(raffleId, header): owner revokeMinter(raffle); any claim(raffleId, pool, wins) reverts NotMinter(raffle) until a new 7-day proposal is activated. (e) owner: renounceOwnership() on OGClubStaking before grantSpender(raffle) -> enter() can never succeed (NotSpender) and no owner exists to grant.","severity":"info","snippet":"    function proposeSeason(bytes32 root, uint256 total) external onlyOwner nonReentrant returns (uint256 seasonId) {","title":"Owner trust assumptions that bound but do not prevent value extraction (documented in README; recorded for the judge)"}],"hash":"3969e67ff9e4a1eeecb47e4a28356fbd94c873196df7dcc23c71c7faa9bca1f2","nodeId":"fd6e69f3-743e-49e2-bc2b-1ae67184e1bd","outcome":"completed","summary":"Findings file validated: both snippets match the tree exactly, JSON parses, and all 41 listed entry points plus three invariant rows are covered.\n\n**Result: no critical or high defects in the permissions area.** The access-control, trust-gap and asymmetry passes over all four contracts found the permission model consistent, and the full suite of 104 tests passes on this tree.\n\nWhat I checked and how it came out:\n\n- **Role lifecycle** in staking and furniture mirrors exactly: one immediate bootstrap grant, 7-day proposals, inclusive 7-day activation window, cancel and activate share one liveness predicate, revoke clears both state slots. Confirmed the lapse instant with a scratch test.\n- **Window boundaries** are complementary at every pair: enter vs cancelRaffle, enter vs commitDraw, vault claim vs cancelSeason and vs releaseSeason. No instant where two sides disagree.\n- **Owner custody**: no selector moves stakes, points or vault tokens. The only vault outflow is a Merkle claim paid to the leaf account.\n- **claimTo** correctly rejects interleaved wallets per group, zero recipients and reentry.\n- **launch.json** has only the three schema keys, in-order constructor arguments, backward references, and notes under the limit.\n\nFindings written to `.imd-findings.json`:\n\n1. **Low.** Permissionless `claim` cannot be declined by the entry wallet. A contract wallet that accepts ERC-1155 but has no outbound transfer receives its prize from a stranger's `claim`, and its own `claimTo` then reverts as already claimed. Reproduced in a scratch test. This follows the brief's wording, so it is flagged as a design gap for the author to decide.\n2. **Info.** Documented owner trust assumptions recorded with concrete sequences: Merkle self-allocation bounded to half the unreserved pool per 7 days, any spender can burn any account's points, any minter can mint freely, revoking the raffle blocks delivery, and renouncing ownership is immediate.\n\nNot reached: the randomness bias of re-targeting after 256 blocks is outside my area and already documented in the README, so I did not quantify it. The scratch tests live under `test/scratch/` and are not part of the submission.","treeHash":null,"usage":{"cachedInputTokens":788584,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":35052,"runtime":"claude","turns":24,"wallClockMs":510878}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"7e50667f872c7f5e","findings":[{"citation":"resolved","description":"OGClubStaking deliberately defers the decimals() read to the first stake (src/OGClubStaking.sol:71-75) so that the factory constructor never calls a dependency. That moves the only validation of the token's metadata to the first outside caller. The deploy helper, which runs against the live chain and is the place meant to catch configuration mistakes ('TOKEN must be an existing token'), checks only that the address is non-zero. If TOKEN points at a contract without decimals() (or one returning > 18, or an EOA / typo address), all four contracts deploy successfully, ownership is assigned, and roles can be granted, but every stake() call reverts forever: `token` and `vault` are immutable and there is no setter, so the staking contract (and therefore the raffle, whose points come only from it) is dead and must be redeployed. No funds are at risk because nothing can be deposited; the impact is a wasted mainnet deployment and the owner Safe operations that follow it. Suggested minimal fix: in Deploy.run() (or deploy()), call IERC20Metadata(token).decimals() and revert InvalidConfiguration if it reverts or exceeds 18, and assert token.code.length != 0. This keeps constructors dependency-free, as the launch policy requires, while failing fast off-chain.","line":36,"path":"script/Deploy.s.sol","reproduction":"State: fresh chain. Input: Deploy.deploy(address(new NoDecimalsToken()), owner, 1e18, 0) where NoDecimalsToken is a working ERC-20 that simply omits decimals() (contract in the description's scratch test). Expected: the deployment preparation refuses the token. Actual: all contracts deploy; then token.approve(staking, 1 ether); staking.stake(1 ether) reverts (the staticcall to decimals() fails inside the `if (accrualDenominator == 0)` branch), staking.totalStaked() stays 0, and no later call can ever make stake() succeed because `token` is immutable. Verified with a Foundry test: forge test --match-path test/scratch/DecimalsProbe.t.sol passes with vm.expectRevert() around stake().","severity":"low","snippet":"        if (token == address(0) || owner == address(0)) revert InvalidConfiguration();","title":"Deploy script accepts a TOKEN whose decimals() reverts, producing an immutable staking deployment where stake() can never succeed"},{"citation":"resolved","description":"This is the requested design ('first grant immediate, later grants are 7-day proposals'), not a defect; it is recorded because the brief asks that privileged powers be documented with their actor and preconditions. Until the owner has made the first grant in each contract, the owner (the Safe on mainnet) can, in one transaction, authorise any address as spender (OGClubStaking) or minter (OGClubFurniture, same pattern at src/OGClubFurniture.sol:55-59). A spender may call spendPoints(account, amount) for any account, which is the one path by which points leave an account; a minter may mint any furniture id in any quantity. After that single grant, every further authorisation is a visible 7-day proposal with a 7-day activation window and can be cancelled or revoked. The launch.json notes and README state that the first grant in each contract must be the raffle; the contracts cannot enforce that ordering. Stakers who deposit before the owner has made the first grant rely on the owner using it for the raffle.","line":122,"path":"src/OGClubStaking.sol","reproduction":"State: freshly deployed OGClubStaking with bootstrapped == false, alice has staked 10 OG for 1 day (pointsOf(alice) == 10e18). Input: owner calls grantSpender(ownerEOA) then ownerEOA calls spendPoints(alice, 10e18) in the same block. Expected under the documented operating procedure: the first grant goes to the raffle. Actual: both calls succeed with no delay, pointsOf(alice) == 0, and the only signal is the SpenderSet event. The same sequence with grantMinter(ownerEOA) then mintBatch(ownerEOA, [1], [1000]) mints 1000 units of item 1 outside any raffle. Any second attempt (bootstrapped == true) emits SpenderProposed/MinterProposed and cannot take effect before 7 days.","severity":"info","snippet":"        if (!bootstrapped) {\n            bootstrapped = true;\n            delete pendingSpenders[spender];\n            spenders[spender] = true;","title":"Trust assumption: the first grantSpender / grantMinter after deployment is immediate, so the owner can authorise an arbitrary spender or minter with no delay once"}],"hash":"4083327bc84cc3f054beb8c5c67b9cae444cd26700fb80add047e52f78593370","nodeId":"1ce68374-f88b-47d2-8e4b-49991f5bb491","outcome":"completed","summary":"The review is complete and the findings file is written. The working tree is otherwise untouched (scratch tests and python caches removed).\n\n**Outcome: no critical, high or medium defects in the control-flow area.** I report one low finding and one documented trust assumption, with 47 coverage rows answering all 41 entry points plus six invariants.\n\n**What I traced**, against the Execution Trace, Periphery and First Principles guides:\n- **OGClubRaffle**: create/enter/commit/draw/claim state machine, exact window boundaries, the retarget rule (draw window is `(target, target+256]`, recommit only at `target+257`, which matches `blockhash` availability exactly), claim grouping and bitmap ordering, reentrancy across the ERC-1155 receiver hook.\n- **Periphery libraries**: `BlockHeader` RLP parser (canonical-length rules, bounds, field 8 and 13 checks) and `Permutation` (balanced Feistel with cycle walking is a bijection; I measured near-uniform output at sizes 2, 3 and 4 over 4000 seeds). The Sepolia fixture 11921684 was re-fetched from two live RPCs and matches the embedded hash and mixHash. The python encoder tests pass when run directly.\n- **OGClubStaking** accrual math (144-bit intermediate, remainder carry), fee rounding, balance-delta credit, callback guards, spender lifecycle. **OGClubFarmVault** budget, interval, claim window and release. **Deploy.s.sol** and **launch.json** argument order and dependency order.\n\n**Findings written to `.imd-findings.json`:**\n1. **Low**: the deploy helper validates only that `TOKEN` is non-zero. Because staking defers its `decimals()` read to the first stake, a token lacking that getter deploys fine and then `stake()` reverts forever with no recovery, since `token` is immutable. Reproduced with a Foundry scratch test. Fix: call `decimals()` in the script's `run()` and revert if it fails or exceeds 18.\n2. **Info**: the one immediate first `grantSpender`/`grantMinter` is the requested design, recorded as a trust assumption with the concrete sequence by which a fresh owner could burn points or mint furniture without delay before the raffle is granted.\n\n**Not reached in depth**: the README gas table and EIP-8037 slot projections, and the economics of the mainnet OG token itself. Those belong to other specialists' areas.","treeHash":null,"usage":{"cachedInputTokens":1659965,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":41697,"runtime":"claude","turns":42,"wallClockMs":643269}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"f494611affb5524c","findings":[{"citation":"resolved","description":"The per-wallet cap is only enforced when pool.maxTicketsPerWallet != 0 (line 189), but the running total ticketsOf[raffleId][poolId][wallet] is written unconditionally. For a pool created with maxTicketsPerWallet = 0 (the README's 'unlimited' case and the default in every test pool) the slot is never read by any guard. Under the EIP-8037 model the project itself documents (97,920 state gas per fresh slot), each wallet's first entry into each uncapped pool pays for one durable slot that carries no protocol meaning. This is a gas/efficiency note against the brief's stated goal of minimising fresh slots, not a correctness or funds defect; the window, cap and range arithmetic in enter() are otherwise exact at the boundaries ([opensAt, closesAt), cap at exactly maxTicketsPerWallet, ticketsSold + tickets <= 2^48-1).","line":195,"path":"src/OGClubRaffle.sol","reproduction":"Run `forge test --match-contract GasTest --match-test test_GasEnter --isolate -vv`. The pool from pools(10) has maxTicketsPerWallet = 0, yet the test reports 'New persistent slots: 4' for alice's first entry: the entries array length, the Entry slot, alice's staking points slot, and ticketsOf[id][0][alice]. Expected for an uncapped pool: 3 fresh slots (ticketsOf unused). Afterwards `raffle.ticketsOf(id, 0, alice)` returns 10 although no cap applies. Minimal fix: only read/write ticketsOf when pool.maxTicketsPerWallet != 0 (the Entered event already exposes per-entry ranges off chain).","severity":"info","snippet":"        ticketsOf[raffleId][poolId][msg.sender] = walletTickets;","title":"enter() writes a ticketsOf slot for every wallet even in uncapped pools, adding one fresh EIP-8037 slot per wallet per pool that nothing enforces"},{"citation":"resolved","description":"The brief anticipates a fee-on-transfer OG token on the stake path (credit only what is received), and stake() handles that correctly. On the exit path the contract insists that its own balance drops by exactly `amount` across the two outbound transfers. That is the right choice for recipient-side taxes (the vault and the staker simply receive less) and it correctly refuses to let a sender-side tax be paid out of other stakers' deposits. But if the production OG token debits the sender more than the transferred amount (burn-from-sender or reflection style), the check fails for every amount, there is no alternative exit, and all staked OG is unrecoverable. The README lists such tokens as unsupported; this is recorded here as an explicit mainnet deployment precondition rather than a code defect, because the alternative (tolerating the shortfall) would break the staking-balance == totalStaked invariant.","line":98,"path":"src/OGClubStaking.sol","reproduction":"Existing test test_ZeroReceiptAndSenderSideFeeRevertAtomically (test/OGClubStaking.t.sol:138-153): TestToken.configureFee(1000, true) makes transfers burn 10% from the sender in addition to the amount; after stake(100 ether), unstake(10 ether) reverts with UnexpectedTokenDebit and stakeOf(alice) stays 100 ether; no call sequence recovers the tokens. Before mainnet deployment, confirm with a 1-wei transfer from a fresh wallet that the OG token's sender balance decreases by exactly the transferred amount; if it does not, this contract must not be used with that token.","severity":"info","snippet":"        if (token.balanceOf(address(this)) != beforeBalance - amount) revert UnexpectedTokenDebit();","title":"Trust assumption: unstake() requires the token to debit exactly `amount`; a token with any sender-side transfer tax makes every unstake revert and leaves all stakes locked"}],"hash":"6b497bf6b1052c4eafe3e0c8b31eb2aa83a34cbd8f04052fb30ea1837c9744b3","nodeId":"71ae106d-99e8-43bf-9c9a-fcb294f79809","outcome":"completed","summary":"The review is complete and written to `.imd-findings.json` (valid JSON, two findings, 46 coverage rows covering all 41 listed entry points plus five invariants). The scratch probe tests were removed, so the tree holds only the findings file.\n\n**Outcome: no medium-or-higher defect in the math, boundary or numerical-gap area.** The arithmetic held up under every check I ran against the Pashov Math Precision, Boundary and Numerical Gap guides:\n\n- **Staking accrual** is an exact floor of `balance × rate × seconds / (86400 × 10^decimals)` with the sub-unit remainder carried in a `uint80`. Intermediates fit (≤ 2^272 through 512-bit `mulDiv`, result < 2^256 even at the uint128/uint96/uint48/0-decimals corner). Probed at 0 decimals and via the existing 0–18 decimal fuzz.\n- **Unstake fee** is `ceilDiv(amount, 100)`: 1 wei pays 1 wei, 100 pays 1, 101 pays 2. No way to dodge it by splitting.\n- **Permutation** is a balanced 8-round Feistel with cycle walking on the next power-of-four domain. I verified it exhaustively as a bijection at sizes 2, 3, 4, 5, 16, 17 (20 keys each) and 1025, beyond the repo's fuzz to 200. Domain limit 2^48 matches `MAX_TICKETS`.\n- **Draw window** `target < block.number ≤ target + 256` matches BLOCKHASH availability exactly, and re-targeting opens at the first block where the old hash is gone. The RLP decoder is bounds-checked at every read.\n- **Vault cap** floors `(balance − reserved) / 2`; probed with 3, 2 and 1 wei unreserved. Claim window and release boundary meet at exactly `opensAt + 90 days`.\n- **README gas table** reproduces exactly from the isolated gas test, and `launch.json` is schema-valid with correct argument counts.\n\n**Two informational notes were recorded,** each with a concrete reproduction:\n\n1. `enter()` writes a `ticketsOf` slot even for uncapped pools, costing one unenforced fresh slot per wallet per pool under EIP-8037 (the gas test shows 4 fresh slots where 3 would suffice).\n2. `unstake()` requires the token to debit exactly `amount`. That is the right protective choice, but a sender-taxed OG token would lock every stake, so it is flagged as a mainnet deployment precondition rather than a code defect.\n\nStatic-analysis leads in my area (weak-prng on the remainder modulus, strict equalities, uninitialized locals, unsafe casts in `enter`) were all traced and are false positives: the casts are guarded by prior range checks and the equalities are intentional sentinels.","treeHash":null,"usage":{"cachedInputTokens":1512269,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":46923,"runtime":"claude","turns":40,"wallClockMs":701804}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"4ebee02fc506f27c","findings":[{"citation":"resolved","description":"The season mechanism is the only token-moving path and the owner alone chooses root and total. Nothing ties a root to staker activity, so the 50%/7-day budget is the effective drain rate of unstake fees to any address the owner picks. README lines 219-220 already state this. Recorded so the judge has the actor, precondition and rate; it is not a permission bypass and the design (owner-published Merkle seasons) is what the brief requests. Mitigation if wanted would be a design change (e.g. timelocked root publication or a committee owner), which the README recommends by requiring OWNER to be a Safe on mainnet.","line":59,"path":"src/OGClubFarmVault.sol","reproduction":"Vault funded with 1000e18. Owner: proposeSeason(leaf(1, owner, 500e18), 500e18); warp +3 days; claim(1, owner, 500e18, []) -> owner receives 500e18. warp +4 days (7 days since proposal): proposeSeason(leaf(2, owner, 250e18), 250e18); +3 days claim; repeat once more with 125e18. After 3 seasons (14 days) the owner holds 875e18 of the 1000e18 fees; the vault keeps 125e18. Verified in test/scratch/EconProbe.t.sol test_OwnerSelfPayoutRate (passes on current code, i.e. the behaviour is as designed).","severity":"info","snippet":"        if (total > (token.balanceOf(address(this)) - reserved) / 2) revert BudgetExceeded();","title":"Owner can route up to half the unreserved vault to any recipient (including itself) every 7 days via seasons; documented trust assumption, not a bypass"},{"citation":"resolved","description":"stake() is tolerant of fee-on-transfer tokens (it credits the delta), but unstake() and OGClubFarmVault.claim() require the contract's balance to drop by exactly `amount`. If the production OG token (an operator input, not in this repo) ever charges the sender on top of the transferred amount, or later enables such a tax, stake exits and vault payouts revert permanently while stake() keeps accepting deposits. README lines 104-106 document this as intended ('extra sender-side fees revert atomically'), so this is a dependency assumption to verify at deployment rather than a code defect. Suggested evidence before mainnet launch: a fork test that stakes and unstakes against the real OG token address.","line":98,"path":"src/OGClubStaking.sol","reproduction":"TestToken(18); OGClubStaking(token, vault, owner, 1e18). alice stakes 100e18 (token fee 0). Then token.configureFee(1, true) (0.01% charged to the sender in addition to the amount). alice unstake(50e18) -> reverts UnexpectedTokenDebit; stakeOf(alice) stays 100e18 and nothing can be withdrawn while the tax is active. Verified in test/scratch/EconProbe.t.sol test_SenderSideFeeLocksStake.","severity":"info","snippet":"        if (token.balanceOf(address(this)) != beforeBalance - amount) revert UnexpectedTokenDebit();","title":"A token that debits the sender more than the requested amount (sender-side tax) makes every unstake and vault claim revert; mainnet TOKEN must be verified to debit exactly"},{"citation":"resolved","description":"commitDraw is permissionless and sets target = current block + 3. Proposer schedules are public roughly an epoch ahead and a proposer knows its own RANDAO reveal in advance, so a validator with tickets can send commitDraw three blocks before its own slot, compute the resulting seed and winners off-chain, and either propose (favourable) or skip the slot (unfavourable; the next proposer's reveal is then unknown to it). Cost per attempt is about one block proposal reward; gain is one re-roll per attempt. With no independent keeper calling draw(), the 257-block retarget rule gives the same party further re-rolls. The README (lines 165-175) and the brief explicitly accept on-chain future-block randomness and document the withholding bias; this row quantifies the cheapest version so the operator can size prizes and keeper coverage accordingly. No code change is implied by the brief; a VRF would be a design change.","line":209,"path":"src/OGClubRaffle.sol","reproduction":"Pool with 1 prize, attacker holds t of T tickets. Attacker is scheduled proposer for slot S. At block S-3 attacker calls commitDraw(id) -> targetBlock = S. Attacker computes prevRandao_S = mix_{S-1} xor hash(own reveal) and evaluates winningTicket(id, 0, 0) off-chain. If it is not one of its tickets, attacker skips slot S (block at height S is built by a later proposer with an unpredictable randao); probability of winning rises from t/T to roughly 1-(1-t/T)^2 per skipped block. With t/T = 0.1 that is 0.19 for one skipped proposal (~0.04 ETH forgone at current reward levels).","severity":"info","snippet":"        raffle.targetBlock = (block.number + TARGET_DELAY).toUint64();","title":"Draw seed bias: the committer can align the target with a slot it proposes and discard an unfavourable prevRandao for the price of one missed block; retargeting repeats the choice"}],"hash":"893664d8c088224149a05419c5aeabcc91277fa429288d0ac72074d295b9b85f","nodeId":"582a14b1-18da-464b-a0a7-22e98dababcf","outcome":"completed","summary":"The review is complete and the findings file is written. Here is the recap.\n\n**Outcome: no defects found in the economics area.** The `.imd-findings.json` file holds three info-level trust notes and a 47-row coverage record, with every one of the 41 listed entry points marked `holds` plus six invariant rows.\n\n**What I checked, against the Pashov Economic Security, Invariant and Flow Gap guides**\n\n- **Staking:** accrual is exact (full-precision mulDiv plus a carried remainder, so checkpoint frequency never changes points). The fee is ceil(amount/100), so 1-wei chunks cannot dodge it. Stake credits the balance delta, so a fee-on-transfer token cannot inflate stake. Flash staking earns nothing and loses 1%. The balance-equals-totalStaked invariant survives both the plain and the 2% recipient-fee token.\n- **Raffle:** entries are recorded before the point spend so a failed spend rolls back the range and cap. Both selection permutations are keyed Feistel bijections with cycle walking over the exact domains, so exactly min(prizes, tickets) distinct tickets win and each item is minted at most its quantity. Claims are O(wins), bitmap-guarded, and mint only to the entry wallet. The claimTo redirect checks the wallet at every group boundary.\n- **Vault:** the 50% budget is computed against the unreserved balance, reserved at once, and the 7-day interval is measured from the proposal even after cancel. Claims decrement remaining and reserved before transfer and check the exact debit. Balance ≥ reserved cannot break with an honest token.\n- **Documentation and manifest:** I re-ran the gas test in isolation and all six README rows match exactly. The manifest has only the three schema keys, five unique contract names in dependency order, string arguments one per constructor parameter, and 2,051 characters of notes. Full suite, fmt check and Python header tests all pass.\n\n**The three info notes** record trust assumptions the judge should weigh, each with a verified reproduction in `test/scratch/EconProbe.t.sol`:\n\n1. The owner can route half the unreserved vault to any recipient, including itself, every 7 days through seasons. Over three seasons that is 875 of 1000 fee tokens. This is the brief's design and the README says so.\n2. A token that debits the sender more than the requested amount makes every unstake and vault claim revert while stake keeps accepting deposits. The README documents it, but the mainnet OG token should be fork-tested before launch.\n3. The cheapest seed bias is a validator calling commitDraw three blocks before its own slot and skipping the slot if the computed seed is unfavourable, roughly doubling its odds for one missed block reward. The README documents the general withholding bias; this quantifies it.\n\nNothing in the tree was modified beyond the findings file and the scratch test directory.","treeHash":null,"usage":{"cachedInputTokens":1449230,"inputTokens":386,"model":"claude-fable-5-1","outputTokens":41546,"runtime":"claude","turns":37,"wallClockMs":660445}},{"artifacts":[],"attempt":1,"bundleHash":"462c0013f72432d67fe7928ce51e197dbb15e229ab4960bdfa8451b21bb2f544","device":"1d2eacca0a6e8449","findings":[],"hash":"94de2a823fd09f60c7f64e03a015e0f58a6f103225ed5e5937ffc9056a70c9ee","nodeId":"e751d721-8aab-4641-95b0-ab4d44025551","outcome":"completed","summary":"Updated only [launch.json](/home/imd-worker/.identitymd/work/13140792-b1a6-4db9-b76c-61cfbc5cfe80/e751d721-8aab-4641-95b0-ab4d44025551/launch.json), preserving the five verified constructor entries and clarifying required owner role grants.\n\nPassed `forge build`, `forge test` with the supplied fuzz seed, `forge fmt --check`, and manifest ABI validation. Nothing deployed.","treeHash":"216b2a4958542121a2e536a731fbbc2f90c6d8ef","usage":{"cachedInputTokens":342912,"inputTokens":36752,"model":"gpt-6-astra","outputTokens":3803,"runtime":"codex","turns":4,"wallClockMs":111633}},{"artifacts":[],"attempt":1,"bundleHash":"ba6ef88b8c74cbee3df6d2430d2468b1d124602ff1c979133df823583710d582","device":"726aa3006eb6a1e1","findings":[],"hash":"9ce19b60fb0b959a769b007fbf46fecc46ffa2bb4025e5cb8cd7b8149b9c1f2f","nodeId":"f83de20f-b64c-44f6-ab0d-4ea253e2a77a","outcome":"completed","summary":"Added 12 regression/fuzz tests and three stateful invariant campaigns, covering fee conservation, raffle lifecycles, partial payouts, and failure rollback. All changes are under `test/`.\n\nVerified:\n- 119 Foundry tests passed with the required seed.\n- `forge build` and `forge fmt --check` passed.\n- Six offline Python checks passed.\n\nNo implementation defects were reproduced. Nothing was deployed.","treeHash":"23ec9e1ec81e568e3613b96ccbfca6e7467ca928","usage":{"cachedInputTokens":3757952,"inputTokens":163756,"model":"gpt-6-astra","outputTokens":31217,"runtime":"codex","turns":10,"wallClockMs":862334}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"782f24113d209be2","findings":[{"citation":"resolved","description":"activateMinter only checks that the 7-day delay has elapsed; it has no upper bound. The requirement (brief item 4, and the staking spender rule that mirrors it) is that a proposal lapses unless it is activated within 7 days after its delay ends, i.e. activation must revert once block.timestamp > activatesAt + MINTER_DELAY. On this code a proposal the owner made and forgot (or made for an address later found to be wrong, without calling cancelMinter) remains a live, permissionless grant of unlimited furniture minting at any later time, so the 7-day public notice no longer bounds when a new minter can appear. The existing suite never asserts a late activation fails (test_CancelStopsActivationEvenAfterDeadline only checks cancel). Fix: store the proposal timestamp and revert in activateMinter when block.timestamp > activatesAt + MINTER_DELAY (and treat such a proposal as absent for cancel/grant bookkeeping), with tests at activatesAt + 7 days (ok) and + 7 days + 1 (revert).","line":71,"path":"src/OGClubFurniture.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {OGClubFurniture} from \"src/OGClubFurniture.sol\";\n\n/// @notice A minter proposal must lapse once 7 days have passed after its delay ended (activatesAt + 7 days).\n///         On the current code a proposal never lapses: a forgotten proposal can be activated by anyone, years later.\ncontract MinterProposalLapseTest is Test {\n    OGClubFurniture internal furniture;\n    address internal owner = makeAddr(\"owner\");\n    address internal raffle = makeAddr(\"raffle\");\n    address internal stale = makeAddr(\"stale\");\n    address internal stranger = makeAddr(\"stranger\");\n\n    function setUp() public {\n        vm.warp(1_700_000_000);\n        furniture = new OGClubFurniture(owner, owner);\n        vm.prank(owner);\n        furniture.grantMinter(raffle); // the one immediate grant spends the bootstrap\n        assertTrue(furniture.bootstrapped());\n    }\n\n    function test_ProposalLapsesSevenDaysAfterMaturity() public {\n        vm.prank(owner);\n        furniture.grantMinter(stale);\n        uint256 activatesAt = furniture.pendingMinters(stale);\n        assertEq(activatesAt, block.timestamp + 7 days);\n\n        // Still activatable at the last second of the 7-day activation window.\n        vm.warp(activatesAt + 7 days);\n        // One second later the proposal has lapsed: activation must revert and grant nothing.\n        vm.warp(activatesAt + 7 days + 1);\n        vm.prank(stranger);\n        (bool ok,) = address(furniture).call(abi.encodeWithSelector(furniture.activateMinter.selector, stale));\n        assertFalse(ok, \"lapsed proposal was still activatable\");\n        assertFalse(furniture.minters(stale), \"lapsed proposal granted minting\");\n\n        // Far later it must still be dead.\n        vm.warp(activatesAt + 365 days);\n        vm.prank(stranger);\n        (ok,) = address(furniture).call(abi.encodeWithSelector(furniture.activateMinter.selector, stale));\n        assertFalse(ok, \"year-old proposal was still activatable\");\n        assertFalse(furniture.minters(stale), \"year-old proposal granted minting\");\n    }\n\n    function test_ProposalStillActivatesInsideItsWindow() public {\n        vm.prank(owner);\n        furniture.grantMinter(stale);\n        uint256 activatesAt = furniture.pendingMinters(stale);\n        vm.warp(activatesAt + 7 days);\n        vm.prank(stranger);\n        furniture.activateMinter(stale);\n        assertTrue(furniture.minters(stale));\n    }\n}","reproduction":"Deploy OGClubFurniture(owner, owner); owner.grantMinter(raffle) (bootstrap spent). owner.grantMinter(stale) at t0 -> pendingMinters[stale] = t0 + 7 days. vm.warp(t0 + 14 days + 1) (or t0 + 365 days); anyone calls activateMinter(stale). Expected: revert (proposal lapsed at t0 + 14 days). Actual: succeeds, minters[stale] == true and stale can mintBatch any id/quantity. Proof: test/scratch/MinterProposalLapse.t.sol fails with 'lapsed proposal was still activatable'.","severity":"medium","snippet":"        if (block.timestamp < activatesAt) revert MinterDelayNotElapsed(minter, activatesAt);","title":"OGClubFurniture minter proposals never lapse: a stale proposal stays activatable forever"},{"citation":"resolved","description":"The launch forbids pausing and post-deployment configuration; the brief also states 'No pause' for the replacement staking contract and makes the new vault immutable. OGClubBox.setPaused lets the owner stop every buy at will, and setVault (src/OGClubBox.sol:218) redirects the non-burned share of all future purchases to any address chosen after deployment. The brief retires OGClubBox, so the adapter must make sure neither the contract nor these patterns are carried into OGClubStaking / OGClubRaffle / OGClubFarmVault (no pause, vault immutable, nothing settable after the constructor beyond the furniture minter/spender grants the brief names). The current launch.json still deploys OGClubBox and must be rewritten.","line":212,"path":"src/OGClubBox.sol","reproduction":"owner calls box.setPaused(true). A buyer with allowance calls box.buy(seasonId, 1) during [opensAt, closesAt) -> reverts BuyingPaused() although the season is open and the box is an authorized minter. Likewise owner calls box.setVault(attackerEOA); the next buy pays vaultAmt to attackerEOA instead of the vault the season was announced with. Expected for the launched contracts: no such switch exists; the vault is immutable.","severity":"medium","snippet":"    function setPaused(bool value) external onlyOwner {\n        paused = value;\n        emit PausedSet(value);\n    }","title":"OGClubBox carries an owner pause switch (setPaused) and a mutable vault, both outside the launch rules; retire with the box"},{"citation":"resolved","description":"The on-chain BlockHeader.decode accepts any number of trailing fields, but the only supplied off-chain tool refuses a block whose JSON contains blockAccessListHash or slotNumber. The brief requires these two fields to be encoded in order after requestsHash (verified on Sepolia), with Sepolia block 11921684 as a fixture tested for keccak and for draw. Until the encoder is updated, a Sepolia deployment (where those fields are live) has no supported way to build the header for open/draw within the 256-block window, and an operator who hand-edits the JSON to drop the fields produces a header whose keccak no longer matches blockhash(target). The remaining unknown-field refusal must stay.","line":62,"path":"script/encode_header.py","reproduction":"python3 script/encode_header.py sepolia-11921684.json where the eth_getBlockByNumber result contains \"blockAccessListHash\": \"0x...\" and \"slotNumber\": \"0x...\". Expected: RLP of 23 fields whose cast keccak equals the block's published hash. Actual: ValueError('unsupported newer header fields: update the encoder'), exit 1, no header.","severity":"low","snippet":"    if any(block.get(key) is not None for key in (\"blockAccessListHash\", \"slotNumber\")):\n        raise ValueError(\"unsupported newer header fields: update the encoder\")","title":"encode_header.py cannot encode a header with blockAccessListHash / slotNumber, so no draw header can be produced for current Sepolia blocks"},{"citation":"resolved","description":"The manifest in the tree describes MockOG + OGClubFurniture + OGClubBox and must be rewritten for MockOG, furniture, vault, staking, raffle. Two points for the adapter: (1) the recipe allows no post-deployment calls, so the raffle cannot be 'granted as minter and spender' by launch.json; the owner must call furniture.grantMinter(raffle) and staking.grantSpender(raffle) afterwards, and since OGClubFurniture's only immediate grant is the first one ever (bootstrapped), any other address granted first forces the raffle through the 7-day proposal path (and, once item 4 is implemented, a lapse window). The notes must state this order. (2) Constructor dependency order forces raffle after staking and furniture, so a constructor-time grant would need the raffle address before it exists; do not try to solve this with CREATE2 prediction or an initializer, both outside the recipe. Also: the brief says 148 tests pass at db10d56; the tree runs 136 (forge test, verifier seed), so the adapter should not treat a count below 148 as a regression.","line":18,"path":"launch.json","reproduction":"Submit the tree's launch.json for the new design: it instantiates OGClubBox (to be retired) with $owner as vault and omits OGClubStaking/OGClubRaffle/OGClubFarmVault. After a correct deployment with nothing granted, raffle.claim -> furniture.mintBatch reverts NotMinter(raffle) and raffle.enter -> staking.spendPoints reverts for an unauthorized spender until the owner performs the grants. If the owner's first furniture grant goes to any other address, grantMinter(raffle) returns a proposal: minters(raffle) stays false for 7 days.","severity":"info","snippet":"      \"contract\": \"OGClubBox\",","title":"launch.json still deploys the retired OGClubBox; the brief's 'raffle granted as minter and spender' cannot be expressed in a constructor-only manifest"},{"citation":"resolved","description":"MockOG is the brief's testnet payment token and is kept on purpose. Because its mint has no access control, the Sepolia launch.json that lists MockOG as the staking token gives every account unlimited stake, hence unlimited points at pointsPerTokenDay and the ability to buy every ticket of every raffle pool (subject only to maxTicketsPerWallet, which is per wallet and trivially multiplied with fresh wallets). This is acceptable for a test network but the README for mainnet must pass the existing OG token address and the mainnet manifest must not contain MockOG; the launch recipe forbids minting after launch for production contracts.","line":18,"path":"src/mocks/MockOG.sol","reproduction":"On the Sepolia deployment: attacker calls MockOG.mint(attacker, 1e30), approve(staking), staking.stake(1e30); after one day pointsOf(attacker) = 1e12 * pointsPerTokenDay, enough to buy all tickets of any pool. Expected on mainnet: impossible, because the token is the real OG; the manifest must therefore not reuse this file's contract there.","severity":"info","snippet":"    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }","title":"MockOG.mint is unrestricted: on the Sepolia deployment anyone can mint unlimited stake, so points and raffle odds there are meaningless; it must never reach the mainnet manifest"}],"hash":"c193bf4559e16cde56147114630d7adfa7da05b4909673aa88a3666d7a6a66cf","nodeId":"0229a5e4-b2b3-496b-bb85-325bb27d2a85","outcome":"completed","summary":"All five findings now anchor to lines that match the tree, the proof fails on the current code, and nothing under `src/`, `script/`, `test/` (outside the disposable `test/scratch/`), `launch.json` or `README.md` was modified.\n\n## Review result\n\n**Scope read in full:** `src/OGClubBox.sol`, `src/OGClubFurniture.sol`, `src/libraries/BlockHeader.sol`, `src/mocks/MockOG.sol`, `script/Deploy.s.sol`, `script/encode_header.py`, `launch.json`, README, ADAPTATION.md, the test base helper and the furniture and header test lists. `forge build`, `forge fmt --check` and `forge test` with the verifier seed pass. The tree runs 136 tests, not the 148 the brief states.\n\n**Not reached:** the two protected probes need verifier-generated environment inputs and were not executed. The Sepolia header field order the brief mentions was not verified on chain, since no Sepolia endpoint is among the ones this task allows. The three new contracts do not exist yet, so nothing about them could be audited beyond how the kept code constrains them.\n\n**Findings written to `.imd-findings.json`:**\n\n- **Medium, furniture proposals never lapse.** `activateMinter` has no upper bound, so a proposal made and forgotten is a live, permissionless minting grant years later. The brief's item 4 requires lapse 7 days after maturity. Proof test under `test/scratch/MinterProposalLapse.t.sol` fails now with \"lapsed proposal was still activatable\".\n- **Medium, box pause switch and mutable vault.** `setPaused` and `setVault` are owner controls the launch rules forbid. The box is being retired, so this is a flag for the adapter not to carry the pattern into staking, raffle or vault.\n- **Low, header encoder refuses current Sepolia blocks.** Any block JSON carrying `blockAccessListHash` or `slotNumber` raises an error, so no header can be produced for `open` or the future `draw` on Sepolia until the encoder is updated.\n- **Info, stale manifest and an impossible manifest step.** `launch.json` still deploys the box. The brief's \"raffle granted as minter and spender\" cannot be done by a constructor-only manifest; the owner must grant it afterwards, and the furniture's single immediate grant means the raffle must be the very first grant.\n- **Info, MockOG mint is open.** On Sepolia anyone can mint unlimited stake and buy every raffle ticket. Fine for a testnet, but it must not appear in the mainnet manifest.\n\nThe core box logic looked sound against the checklist: payments settle before state is read, balance deltas reject fee-on-transfer, header decoding is canonical and fuzzed, the reveal window and expiry boundaries are off-by-one correct, reentrancy guards cover all four purchase paths, and the ten-pack and cap accounting match the documentation. No critical or high defect was found in the delivered code.","treeHash":null,"usage":{"cachedInputTokens":1010979,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":27750,"runtime":"claude","turns":25,"wallClockMs":426092}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"dff6c0d3de4aa913","findings":[{"citation":"resolved","description":"OGClubStaking defers the decimals() read to the first stake (src/OGClubStaking.sol:71-75) so that constructors never call dependencies, which the launch factory requires. That moves the only validation of the token to the first outside caller. Deploy.deploy(), whose own comment says 'TOKEN must be an existing token', checks only that the address is non-zero. If TOKEN is an EOA, a typo address, or a contract without decimals() (or returning more than 18), all four contracts deploy and ownership is assigned, but every stake() reverts forever: token and vault are immutable and there is no setter, so staking (and the raffle, whose points come only from it) is dead and must be redeployed. No funds are at risk because nothing can be deposited; the impact is a wasted mainnet deployment plus the Safe operations that follow it. Merged from audit_flow; reproduced. Minimal fix that keeps constructors dependency-free: in Deploy.deploy() require token.code.length != 0 and that IERC20Metadata(token).decimals() returns at most 18, reverting InvalidConfiguration otherwise.","line":36,"path":"script/Deploy.s.sol","reproduction":"Fresh chain. NoDecimalsToken is a working ERC-20 that omits decimals(). Call Deploy.deploy(address(new NoDecimalsToken()), owner, 1e18, 0): expected the deployment helper refuses the token; actual all four contracts deploy. Then alice: token.approve(staking, 1 ether); staking.stake(1 ether) reverts (the staticcall to decimals() inside the accrualDenominator == 0 branch fails), staking.totalStaked() stays 0, and no later call can make stake() succeed because token is immutable. Verified with test/scratch/Repro.t.sol::test_DeployAcceptsTokenWithoutDecimalsThenStakeIsDead (passes on current code, demonstrating the behaviour).","severity":"low","snippet":"        if (token == address(0) || owner == address(0)) revert InvalidConfiguration();","title":"Deploy script accepts a TOKEN whose decimals() reverts, producing an immutable staking deployment where stake() can never succeed"},{"citation":"resolved","description":"claim() may be called by anyone and always mints to the entry wallet, while claimTo() is restricted to the entry wallet so contract wallets can choose a destination. The entry wallet has no way to opt out of permissionless delivery. For an entry wallet that is a contract returning the ERC-1155 magic values but exposing no outbound transfer path, a stranger's claim() front-runs or pre-empts the wallet's claimTo() and the prize stays in that contract; the win bit is then set so claimTo() reverts AlreadyClaimed. This matches the brief's literal wording ('claim(raffleId, pool, wins): anyone ... mints prizeOf(k) to the entry's wallet'), so it is recorded as a design gap for the author to decide rather than a defect; only rejecting receivers are protected today. Merged from audit_permissions; reproduced. If the author wants to close it without changing the brief's permissionless claim: in _claim with redirect == 0, skip or revert for entries whose wallet has code, or let the wallet record a redirect once that later permissionless claims honour.","line":253,"path":"src/OGClubRaffle.sol","reproduction":"Raffle 1, pool 0, one prize (item 7); entry 0 belongs to contract W that implements onERC1155Received/onERC1155BatchReceived but has no function that calls safeTransferFrom. After draw: (1) stranger calls claim(1, 0, [{k:0, entry:0}]) -> succeeds, furniture.balanceOf(W, 7) == 1. (2) W calls claimTo(1, 0, [{k:0, entry:0}], alice) -> reverts AlreadyClaimed. Expected: W, the only party entitled to the prize, picks its destination. Actual: the prize is locked in W. Verified with test/scratch/Repro.t.sol::test_StrangerClaimPreemptsClaimToOfAcceptingContractWallet (passes on current code, demonstrating the behaviour).","severity":"info","snippet":"        _claim(raffleId, poolId, wins, address(0));","title":"Permissionless claim() pre-empts a contract wallet's claimTo() destination; a receiver that accepts but cannot forward ERC-1155 keeps the prize"},{"citation":"resolved","description":"These are the requested design, not bypasses; the README (role section and 'Randomness and owner trust') states them. Recorded once, merging the identical observations of audit_flow, audit_economics and audit_permissions, so the judge has actor and preconditions. (a) Vault self-allocation: the owner alone chooses root, recipients and total; nothing ties a season to staker activity, so unstake fees can be routed to any address, including the owner, at floor(unreserved/2) every 7 days after a 3-day delay. (b) First grant: until bootstrapped is set, grantSpender (src/OGClubStaking.sol:122-126) and grantMinter (src/OGClubFurniture.sol:55-59) take effect immediately, so the owner can authorise an arbitrary EOA once with no delay; the contracts cannot enforce that this grant goes to the raffle. (c) Any authorised spender can zero any account's points via spendPoints; any authorised minter can mint any id/quantity outside raffles. (d) revokeMinter(raffle) after a draw blocks prize delivery until a 7-day re-proposal activates; revokeSpender(raffle) blocks entries. (e) renounceOwnership() is immediate (OZ Ownable2Step does not two-step it); before the raffle's roles are granted it leaves the system permanently non-operational. (f) The per-pool wallet cap is per msg.sender and is split trivially across wallets. No code change is required by the brief; any change alters the agreed design (the README mitigates by requiring OWNER to be a Safe on mainnet).","line":59,"path":"src/OGClubFarmVault.sol","reproduction":"(a) Vault funded with 1000e18. Owner: proposeSeason(root = leaf(1, owner, 500e18), 500e18); warp +3 days; claim(1, owner, 500e18, []) -> owner receives 500e18. Warp to +7 days from the proposal: proposeSeason(leaf(2, owner, 250e18), 250e18); +3 days claim; repeat with 125e18. After 3 seasons (14 days) the owner holds 875e18 of the 1000e18 fees. (b) Fresh OGClubStaking with bootstrapped == false, alice staked 10 OG for 1 day (pointsOf(alice) == 10e18). Owner: grantSpender(eoa); eoa: spendPoints(alice, 10e18) in the same block -> both succeed, pointsOf(alice) == 0. Same with grantMinter(eoa) then mintBatch(eoa, [1], [1000]). (d) After draw(raffleId, header): owner revokeMinter(raffle); any claim reverts NotMinter(raffle). (e) Owner: renounceOwnership() on OGClubStaking before grantSpender(raffle) -> enter() can never succeed (NotSpender) and no owner exists to grant.","severity":"info","snippet":"        if (total > (token.balanceOf(address(this)) - reserved) / 2) revert BudgetExceeded();","title":"Trust assumptions: owner-controlled roles bound but do not prevent value extraction (first grant immediate, spender burns any points, minter mints anything, vault owner self-allocates 50% per 7 days, "},{"citation":"resolved","description":"stake() tolerates recipient-side fee-on-transfer tokens by crediting the received delta, as the brief asks. On the exit path the contract requires its own balance to drop by exactly amount across the two outbound transfers, and OGClubFarmVault.claim() (src/OGClubFarmVault.sol:92) applies the same check. That is the right choice for recipient-side taxes (vault and staker simply receive less) and it correctly refuses to let a sender-side tax be paid out of other stakers' deposits, which would break staking balance == totalStaked. But if the production OG token debits the sender beyond the transferred amount (burn-from-sender or reflection style), or later enables such a tax, every unstake and vault payout reverts while stake() keeps accepting deposits, with no alternative exit. The README documents this as unsupported; it is recorded as a mainnet deployment precondition, merging the identical audit_economics and audit_math notes. Evidence to gather before mainnet: a fork test that stakes and unstakes against the real OG token, or a 1-wei transfer from a fresh wallet confirming the sender's balance falls by exactly the amount.","line":98,"path":"src/OGClubStaking.sol","reproduction":"Existing test test/OGClubStaking.t.sol::test_ZeroReceiptAndSenderSideFeeRevertAtomically: TestToken.configureFee(1000, true) burns 10% from the sender in addition to the amount; after stake(100 ether), unstake(10 ether) reverts UnexpectedTokenDebit and stakeOf(alice) stays 100 ether. With the tax active no call sequence recovers the tokens; disabling the tax restores exits. The same TestToken behind OGClubFarmVault makes claim(seasonId, account, amount, proof) revert UnexpectedTokenDebit.","severity":"info","snippet":"        if (token.balanceOf(address(this)) != beforeBalance - amount) revert UnexpectedTokenDebit();","title":"A token that debits the sender more than the transferred amount makes every unstake and vault claim revert; mainnet TOKEN must be verified to debit exactly"},{"citation":"resolved","description":"commitDraw is permissionless and sets target = block.number + 3. Proposer schedules are public about an epoch ahead and a proposer knows its own RANDAO reveal, so a validator holding tickets can commit three blocks before its own slot, compute the seed and winners off-chain, and propose only if favourable, skipping the slot otherwise (the next proposer's reveal is unknown to it). Cost per attempt is roughly one block reward; gain is one re-roll. If no independent keeper calls draw() within 256 blocks, the retarget rule (line 208) gives the same party further re-rolls. The brief explicitly accepts on-chain future-block randomness and asks that the retarget bias be documented, which the README and the manifest notes do; this row quantifies the cheapest version so the operator can size prizes and keeper coverage. No code change is implied by the brief; a VRF would be a design change. Merged from audit_economics.","line":209,"path":"src/OGClubRaffle.sol","reproduction":"Pool with 1 prize; attacker holds t of T tickets and is the scheduled proposer for slot S. At block S-3 the attacker calls commitDraw(id) -> targetBlock == S. Off-chain it computes prevRandao_S from the known mix and its own reveal and evaluates winningTicket(id, 0, 0). If the ticket is not its own it skips slot S (height S is then built by a later proposer with a randao it cannot predict). Probability of winning rises from t/T to about 1-(1-t/T)^2 for one skipped proposal; with t/T = 0.1 that is 0.19. Deterministic part verified by the existing test test/OGClubRaffle.t.sol::test_RetargetOnlyAt257AndOldHeaderCannotDrawNewTarget: at target + 257 commitDraw picks a new target and a different header decides the seed.","severity":"info","snippet":"        raffle.targetBlock = (block.number + TARGET_DELAY).toUint64();","title":"Draw seed bias: a proposer-aligned commitDraw gives a validator with tickets one re-roll per skipped slot, and retargeting after 256 blocks repeats the choice"},{"citation":"resolved","description":"The wallet cap is only enforced when pool.maxTicketsPerWallet != 0 (line 189), but the running total is written unconditionally. For a pool created with maxTicketsPerWallet = 0 (the README's unlimited case and the default in every test pool) the slot is never read by any guard. Under the EIP-8037 model the README itself uses (97,920 state gas per fresh slot), each wallet's first entry into each uncapped pool pays for one durable slot with no protocol meaning. This is a gas note against the brief's goal of minimising fresh slots, not a correctness defect; the window, cap and range arithmetic in enter() are exact at the boundaries. Merged from audit_math; reproduced. Minimal fix: read and write ticketsOf only when pool.maxTicketsPerWallet != 0 (the Entered event already exposes per-entry ranges off chain).","line":195,"path":"src/OGClubRaffle.sol","reproduction":"Pool from RaffleTestBase.pools(1) has maxTicketsPerWallet = 0. alice: enter(id, 0, 10). Expected for an uncapped pool: no per-wallet counter written. Actual: raffle.ticketsOf(id, 0, alice) == 10 (test/scratch/Repro.t.sol::test_UncappedPoolWritesTicketsOf), and `forge test --match-contract GasTest --match-test test_GasEnter --isolate -vv` reports 4 fresh slots for the first entry (entries length, Entry, alice's staking points slot, ticketsOf) where 3 would do.","severity":"info","snippet":"        ticketsOf[raffleId][poolId][msg.sender] = walletTickets;","title":"enter() writes a ticketsOf slot for every wallet even in uncapped pools, one fresh storage slot per wallet per pool that no guard reads"}],"hash":"daafade608f3c0e289cf79973c9399fcb82c08f92674631a9817684efa036a95","nodeId":"62ab645b-c74f-4694-906d-ea16f7d8bf4d","outcome":"completed","summary":"The review is complete. The findings file is written at the repository root and the working tree is otherwise clean.\n\n**Outcome.** The code holds. I found no critical, high or medium defect, and none of the four specialists' nine reports survived as more than a low. The full suite of 119 Foundry tests, both Python test files and `forge fmt --check` pass on this tree, and all five contracts are well under the size limits.\n\n**What I kept, after reproducing each against the code:**\n\n- **Low:** the deploy script accepts a TOKEN address whose `decimals()` reverts, since it checks only for a non-zero address. The deployment then succeeds but every `stake()` reverts forever because the token is immutable. Reproduced with a scratch test using an ERC-20 that omits `decimals()`.\n- **Info:** permissionless `claim()` can pre-empt a contract wallet's `claimTo()` destination. This follows the brief's literal wording, so it is recorded as a design note, with a reproduction showing the prize landing in an accepting-but-immobile contract.\n- **Info, merged from three specialists:** the owner trust assumptions, including the immediate first grant, spender power over any account's points, the vault owner's 50% per 7 days self-allocation path, and immediate renounce.\n- **Info, merged from two specialists:** a token that debits the sender beyond the transferred amount locks every unstake and vault claim. The README documents this as unsupported, so it is a mainnet precondition to verify.\n- **Info:** the proposer-aligned commit bias and retarget re-roll, which the brief accepts and the README documents.\n- **Info:** `enter()` writes a per-wallet ticket counter even in uncapped pools, one unnecessary fresh slot per wallet per pool.\n\n**My own pass** traced all 41 entry points plus the three requested invariants, the permutation bijection and the manifest. Every row is answered; none is unreached. The Slither and Aderyn leads were all false positives on inspection: the \"weak PRNG\" is a modulo for the accrual remainder, the reentrancy lines are guarded and follow checks-effects-interactions, and the unsafe casts are bounded by the prior `MAX_TICKETS` check.\n\n**Housekeeping.** The scratch test directory and the Python cache directories created by running the tests were removed, so no tracked or untracked file in the tree changed.","treeHash":null,"usage":{"cachedInputTokens":1181340,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":38695,"runtime":"claude","turns":31,"wallClockMs":626801}},{"artifacts":[],"attempt":1,"bundleHash":"937706f1e2e1c9c28a7222e8b66d5b35b430c48c19c276156653794f6f2a17ba","device":"29819a9ff9555c6f","findings":[],"hash":"f8a0e15e3266fc53e2704ae3aa08fe2b871eed72f941065bee9434c42e538b7a","nodeId":"af076c2e-387d-4c38-9557-c6edfcbb15d5","outcome":"completed","summary":"Implemented the staking, raffle and farming-vault flow, retired OGClubBox, and updated deployment files, fixtures, README and ADAPTATION.md.\n\nAll checks pass: `forge build`, `forge fmt --check`, 104 permanent Foundry tests with your seed, and six offline checks.\n\nNo deployment performed. The owner must grant the raffle its first minter and spender roles after deployment.","treeHash":"fdb543b279e99374d474257888e23d3dcd53d3f9","usage":{"cachedInputTokens":3271552,"inputTokens":151094,"model":"gpt-6-astra","outputTokens":65006,"runtime":"codex","turns":9,"wallClockMs":1461773}}],"verification":[{"checks":[{"durationMs":10682,"exitCode":0,"name":"build","output":"Compiling 73 files with Solc 0.8.26\nSolc 0.8.26 finished in 10.48s\nCompiler run successful!\n","passed":true},{"durationMs":9323,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 6 tests for test/Gas.t.sol:GasTest\n[PASS] test_GasClaimOne() (gas: 954101)\nLogs:\n  Claim one win / fresh furniture wallet\n  Cancun call gas: 160885\n  New persistent slots: 4\n  EIP-8037 state gas: 391680\n  EIP-8037 storage-repriced call gas: 472565\n\n[PASS] test_GasClaimTen() (gas: 2860761)\nLogs:\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\n  Claim ten distinct items / fresh furniture wallet\n  Cancun call gas: 816170\n  New persistent slots: 22\n  EIP-8037 state gas: 2154240\n  EIP-8037 storage-repriced call gas: 2530410\n\n[PASS] test_GasDraw() (gas: 418645)\nLogs:\n  Draw / 23-field synthetic header\n  Cancun call gas: 74312\n  New persistent slots: 1\n  EIP-8037 state gas: 97920\n  EIP-8037 storage-repriced call gas: 152232\n\n[PASS] test_GasEnter() (gas: 558676)\nLogs:\n  First entry / ten tickets / first points checkpoint\n  Cancun call gas: 155364\n  New persistent slots: 4\n  EIP-8037 state gas: 391680\n  EIP-8037 storage-repriced call gas: 467044\n\n[PASS] test_GasFirstStake() (gas: 200138)\nLogs:\n  First-ever stake / fresh staker\n  Cancun call gas: 120547\n  New persistent slots: 3\n  EIP-8037 state gas: 293760\n  EIP-8037 storage-repriced call gas: 354307\n\n[PASS] test_GasUnstake() (gas: 308132)\nLogs:\n  Partial unstake / first fee / first checkpoint\n  Cancun call gas: 110662\n  New persistent slots: 2\n  EIP-8037 state gas: 195840\n  EIP-8037 storage-repriced call gas: 266502\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 61.22ms (27.67ms CPU time)\n\nRan 7 tests for test/RoleLifecycle.t.sol:RoleLifecycleTest\n[PASS] testFuzz_ExpiredProposalsCannotActivateOrCancel(uint32) (runs: 256, μ: 558669, ~: 558520)\nLogs:\n  Bound result 1\n\n[PASS] test_ActivationAtMaturityAndLastSecond() (gas: 512088)\n[PASS] test_CancelRevokeRegrantAndReproposal() (gas: 800981)\n[PASS] test_InvalidGrantDoesNotSpendBootstrapAndZeroAddressesRejected() (gas: 147761)\n[PASS] test_OnlyOwnerProposesCancelsAndRevokes() (gas: 406632)\n[PASS] test_OwnershipHandoverDoesNotResetBootstrapAndRenunciationDoesNotBlockActivation() (gas: 568368)\n[PASS] test_SpenderLastSecondActivates() (gas: 378503)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 63.97ms (64.03ms CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_ConstructorsDoNotCallDependenciesOrAssignFactoryOwner() (gas: 45432)\n[PASS] test_InvalidConfigurationAndConstructorBounds() (gas: 8014)\n[PASS] test_MockIsDeliberatelyUnlimitedTestnetOnly() (gas: 77458)\n[PASS] test_SepoliaDeploymentAndOwnerSetup() (gas: 34864668)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 78.28ms (81.19ms CPU time)\n\nRan 10 tests for test/BlockHeader.t.sol:BlockHeaderTest\n[PASS] testFuzz_AnyMalformedInputRevertsWithCustomError(bytes) (runs: 256, μ: 32404, ~: 32037)\n[PASS] testFuzz_ArbitraryTrailingFieldCount(uint8,uint256,bytes32) (runs: 256, μ: 92417, ~: 76569)\nLogs:\n  Bound result 14\n\n[PASS] test_MalformedAuthenticatedHeaderCannotMint() (gas: 321913)\n[PASS] test_MalformedRLPBoundsAndCanonicalLengths() (gas: 147737)\n[PASS] test_MissingFieldsAndInvalidNumberOrMixHash() (gas: 237524)\n[PASS] test_RealMainnetCancunHeader() (gas: 543993)\n[PASS] test_RealMainnetPragueHeader() (gas: 547036)\n[PASS] test_RealMainnetShanghaiHeader() (gas: 538038)\n[PASS] test_RealSepoliaHeaderWithAccessListHashAndSlotNumber() (gas: 550588)\n[PASS] test_ZeroNumberAndZeroMixHashAreValidRLP() (gas: 40712)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 87.09ms (146.36ms CPU time)\n\nRan 16 tests for test/OGClubFarmVault.t.sol:FarmVaultTest\n[PASS] testFuzz_ReserveCapAndClaimConservation(uint96,uint96) (runs: 256, μ: 1352248, ~: 1352235)\nLogs:\n  Bound result 488422054035542509857157\n  Bound result 3733446734308\n\n[PASS] test_CancelBeforeOpenOnlyReleasesReserveWithoutTransferring() (gas: 561805)\n[PASS] test_ClaimLastSecondBeforeExpirationAndPartialRelease() (gas: 397391)\n[PASS] test_DelayExactBoundaryAndPermissionlessClaimPaidToAccountOnly() (gas: 442808)\n[PASS] test_FailedTokenTransferRestoresClaimAndReservations() (gas: 727404)\n[PASS] test_HalfCapUsesOnlyUnreservedBalanceAndFloorsOddWei() (gas: 472822)\n[PASS] test_InvalidRecipientsAndZeroAllocation() (gas: 482033)\n[PASS] test_InvalidSeasonRootAndTotal() (gas: 164553)\n[PASS] test_OnlyOwnerCanProposeCancelAndNoSweepOrApprovalOrPause() (gas: 165634)\n[PASS] test_OwnerCallbackCannotReserveAgainstAnInFlightPayout() (gas: 625341)\n[PASS] test_OwnershipHandoverPreservesSeasons() (gas: 415758)\n[PASS] test_ProofRejectsWrongAccountAmountSeasonAndSingleHash() (gas: 898876)\n[PASS] test_ProposalIntervalAtExactBoundaryIncludingAfterCancel() (gas: 441729)\n[PASS] test_ReleaseExactly90DaysAfterOpeningAndNeverWithdrawsTokens() (gas: 562741)\n[PASS] test_TokenCallbackCannotClaimTwice() (gas: 521104)\n[PASS] test_TotalBudgetCapsEvenInconsistentMerkleTree() (gas: 355026)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 105.66ms (101.38ms CPU time)\n\nRan 15 tests for test/OGClubStaking.t.sol:StakingTest\n[PASS] testFuzz_CheckpointFrequencyDoesNotChangePoints(uint96,uint32,uint8) (runs: 256, μ: 1084689, ~: 716801)\nLogs:\n  Bound result 935257245299\n  Bound result 24203\n  Bound result 20\n\n[PASS] testFuzz_FeeRoundsUpAndConservesBalance(uint96) (runs: 256, μ: 282800, ~: 283076)\nLogs:\n  Bound result 13702691596\n\n[PASS] testFuzz_WholeTokenAccrualAcrossSupportedDecimals(uint8,uint96,uint32) (runs: 256, μ: 1219222, ~: 1219409)\nLogs:\n  Bound result 1\n  Bound result 3187696382098\n  Bound result 2319936\n\n[PASS] test_AccrueBeforeBalanceChangesAndNoLock() (gas: 427758)\n[PASS] test_CheckpointsPreserveSubWeiAccrualAndFullExitFraction() (gas: 1366740)\n[PASS] test_DecimalsReadOnFirstUseAndNormalizeWholeTokens() (gas: 2190760)\n[PASS] test_DonationsNeitherCreateStakeNorAwardPoints() (gas: 343342)\n[PASS] test_ExactContinuousAccrualAtBoundariesAndSpend() (gas: 299793)\n[PASS] test_FeeOnTransferCreditsOnlyReceivedAndCannotInflatePoints() (gas: 381142)\n[PASS] test_InvalidAmountsUnauthorizedSpendAndOwnerCannotTouchStakes() (gas: 406963)\n[PASS] test_MaximumPackedBalanceAndRateAccrueWithoutIntermediateOverflow() (gas: 448069)\n[PASS] test_NoReturnAndFalseReturnTokens() (gas: 734103)\n[PASS] test_TinyUnstakesAlwaysPayFee() (gas: 360201)\n[PASS] test_TokenCallbackCannotSpendOrReenterStakeOrUnstake() (gas: 685618)\n[PASS] test_ZeroReceiptAndSenderSideFeeRevertAtomically() (gas: 554565)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 122.98ms (316.88ms CPU time)\n\nRan 3 tests for test/Permutation.t.sol:PermutationTest\n[PASS] testFuzz_LargeDomainsInRangeAndDistinct(uint48,uint48,uint48,bytes32) (runs: 256, μ: 19932, ~: 18133)\nLogs:\n  Bound result 4950\n\n[PASS] testFuzz_SmallDomainsAreBijections(uint8,bytes32) (runs: 256, μ: 637704, ~: 380397)\nLogs:\n  Bound result 6\n\n[PASS] test_InvalidDomainAndIndexRejected() (gas: 211485)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 225.65ms (234.04ms CPU time)\n\nRan 16 tests for test/OGClubFurniture.t.sol:FurnitureTest\n[PASS] testFuzz_AfterFirstMintMustWaitAndAnyoneCanActivate(uint32) (runs: 256, μ: 596126, ~: 595918)\nLogs:\n  Bound result 780\n\n[PASS] testFuzz_EveryGrantAfterTheFirstWaitsSevenDays(address,address,uint32) (runs: 256, μ: 169386, ~: 169450)\n[PASS] test_AllOwnerFunctionsProtected() (gas: 227178)\n[PASS] test_CancelStopsActivationEvenAfterDeadline() (gas: 394671)\n[PASS] test_IdentityInterfacesMintAndSupply() (gas: 448761)\n[PASS] test_InvalidAddressesAndBatchLengths() (gas: 3967)\n[PASS] test_MetadataFreezesPermanently() (gas: 195226)\n[PASS] test_NoOwnerSeizureOrBurn() (gas: 418561)\n[PASS] test_OnlyTheFirstGrantIsImmediateEvenBeforeAnyMint() (gas: 546001)\n[PASS] test_OwnershipTwoStepAndRenounce() (gas: 244214)\n[PASS] test_RegrantingTheRevokedFirstMinterWaitsWithZeroSupply() (gas: 569038)\n[PASS] test_RejectedGrantDoesNotSpendTheBootstrap() (gas: 173991)\n[PASS] test_ReproposalRestartsDelayAndCancelDoesNotRevokeExistingRole() (gas: 457168)\n[PASS] test_RevokeIsImmediateClearsProposalsAndRegrantWaitsAgain() (gas: 535486)\n[PASS] test_RoyaltyDefaultAndLimits() (gas: 161390)\n[PASS] test_ZeroAddressesAndLegacyMinterSelectorCannotGrant() (gas: 340672)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 232.14ms (279.00ms CPU time)\n\nRan 23 tests for test/OGClubRaffle.t.sol:RaffleTest\n[PASS] testFuzz_ExactlyMinPrizesAndTicketsWinWithNoDuplicateTicket(uint8,uint8,bytes32) (runs: 256, μ: 1544577, ~: 1073192)\nLogs:\n  Bound result 9\n  Bound result 8\n\n[PASS] testFuzz_NoticeAlwaysMeasuredFromCreation(uint32) (runs: 256, μ: 241112, ~: 240936)\nLogs:\n  Bound result 2\n\n[PASS] test_ClaimToCannotRedirectAnotherWalletInTheSameBatch() (gas: 1239609)\n[PASS] test_ContractWalletCanRedirectButNobodyElseCan() (gas: 2015153)\n[PASS] test_DrawHeaderAndTargetExactBoundaries() (gas: 641712)\n[PASS] test_DuplicateWithinBatchRollsBackEverythingAndBitmapCrossesWords() (gas: 937264)\n[PASS] test_EntryFailureRollsBackRangesCapsAndPoints() (gas: 833603)\n[PASS] test_EntryWindowAndWalletCapExactBoundaries() (gas: 808341)\n[PASS] test_HugeTicketAndPrizeCountsDoNotRequireIterationToDrawOrClaim() (gas: 925425)\n[PASS] test_InvalidConfigurationPoolsLinesAndTickets() (gas: 941928)\n[PASS] test_Maximum32PoolsAnd128PrizeLines() (gas: 15557738)\n[PASS] test_MultiItemPoolMintsExactQuantitiesIncludingDuplicateAndZeroIds() (gas: 2370129)\n[PASS] test_NoticeExactBoundariesAndCancellation() (gas: 540021)\n[PASS] test_OwnerCannotModifyTermsPauseOrCancelStartedRaffle() (gas: 450829)\n[PASS] test_ReceiverCannotReenterEitherClaimPath() (gas: 1991045)\n[PASS] test_RejectingWalletDoesNotBlockOtherWinnersAndEmptyClaimRejected() (gas: 2030167)\n[PASS] test_RetargetOnlyAt257AndOldHeaderCannotDrawNewTarget() (gas: 560166)\n[PASS] test_RevokedMinterClaimIsRetryableAndDoesNotReroll() (gas: 1017518)\n[PASS] test_TicketPriceMultiplicationOverflowDoesNotSpendOrRecordEntry() (gas: 370843)\n[PASS] test_UnlimitedCapIsPerPoolAndRangesStayContiguous() (gas: 878602)\n[PASS] test_UnsoldPrizesAreRandomPositionsNotAlwaysTheTail() (gas: 3336643)\n[PASS] test_WrongKEntryAndDoubleClaimsRevertAtomically() (gas: 1332250)\n[PASS] test_WrongNumberInAuthenticatedHeaderRejected() (gas: 365306)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 265.91ms (334.69ms CPU time)\n\nRan 1 test for test/VaultInvariant.t.sol:VaultInvariantTest\n[PASS] invariant_VaultAlwaysCoversReservationsAndOnlyClaimsMoveTokens() (runs: 128, calls: 8192, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | advance  | 1307  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | cancel   | 1354  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | claim    | 1366  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1377  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | propose  | 1436  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | release  | 1352  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 1000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 604800\n  Bound result 100000000000000000000\n  Bound result 259200\n  Bound result 345600\n  Bound result 100000000000000000000\n  Bound result 8035200\n  Bound result 3063565111\n  Bound result 855\n  Bound result 4716\n  Bound result 210607787\n  Bound result 240\n  Bound result 20525562795\n  Bound result 12125\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 7798\n  Bound result 5984\n  Bound result 2947\n  Bound result 3689274\n  Bound result 7628737\n  Bound result 400\n  Bound result 192\n  Bound result 2930\n  Bound result 1001\n  Bound result 107477462\n  Bound result 11055\n  Bound result 42\n  Bound result 2879792\n  Bound result 555\n  Bound result 717\n  Bound result 2248\n  Bound result 2755\n  Bound result 7\n  Bound result 6720\n  Bound result 1415071841494791321\n  Bound result 123456\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.43s (2.43s CPU time)\n\nRan 1 test for test/StakingInvariant.t.sol:FeeStakingInvariantTest\n[PASS]\nFeeStakingInvariantTest invariants:\n[PASS] invariant_PointsAppearOnlyByTimeWeightedAccrualAndLeaveOnlyBySpending\n[PASS] invariant_StakingBalanceEqualsAllStakes\n FeeStakingInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| StakingHandler | advance           | 1684  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | spend             | 1645  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | stake             | 1650  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unauthorizedSpend | 1582  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unstake           | 1631  | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10000000000000000000\n  Bound result 86400\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 6264337593543950335\n  Bound result 6277\n  Bound result 2240\n  Bound result 0\n  Bound result 65279\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 1296743294243\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 3068\n  Bound result 128\n  Bound result 0\n  Bound result 0\n  Bound result 1384\n  Bound result 183\n  Bound result 10\n  Bound result 892\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 1\n  Bound result 319379\n  Bound result 4383992273226118098911\n  Bound result 1001\n  Bound result 1001\n  Bound result 1384482842073661969295\n  Bound result 4032\n  Bound result 3\n  Bound result 88\n  Bound result 95\n  Bound result 514264337593543950335\n  Bound result 771998\n  Bound result 149689680\n  Bound result 257\n  Bound result 2792\n  Bound result 10000\n  Bound result 514264337593543950335\n  Bound result 2468\n  Bound result 9\n  Bound result 11\n  Bound result 1001\n  Bound result 7199\n  Bound result 1570148199\n  Bound result 101\n  Bound result 1189\n  Bound result 514264337593543950335\n  Bound result 215\n  Bound result 771998\n  Bound result 21801697765699\n  Bound result 2851\n  Bound result 4976\n  Bound result 96\n  Bound result 4988\n  Bound result 11575608077352841579106\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.30s (3.30s CPU time)\n\nRan 1 test for test/StakingInvariant.t.sol:StakingInvariantTest\n[PASS]\nStakingInvariantTest invariants:\n[PASS] invariant_PointsAppearOnlyByTimeWeightedAccrualAndLeaveOnlyBySpending\n[PASS] invariant_StakingBalanceEqualsAllStakes\n StakingInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| StakingHandler | advance           | 1684  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | spend             | 1645  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | stake             | 1650  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unauthorizedSpend | 1582  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unstake           | 1631  | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10000000000000000000\n  Bound result 86400\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 2264337593543950335\n  Bound result 6305\n  Bound result 0\n  Bound result 2998\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 1296743294243\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 2947\n  Bound result 128\n  Bound result 0\n  Bound result 0\n  Bound result 245\n  Bound result 183\n  Bound result 10\n  Bound result 969\n  Bound result 245\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 0\n  Bound result 36\n  Bound result 854742525\n  Bound result 490\n  Bound result 1\n  Bound result 653867747505\n  Bound result 5713\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 514264337593543950335\n  Bound result 771998\n  Bound result 149689680\n  Bound result 257\n  Bound result 2630\n  Bound result 2180\n  Bound result 514264337593543950335\n  Bound result 1901074597\n  Bound result 9\n  Bound result 11\n  Bound result 56\n  Bound result 5654\n  Bound result 5\n  Bound result 101\n  Bound result 1099\n  Bound result 514264337593543950335\n  Bound result 215\n  Bound result 771998\n  Bound result 1035264338890287252652\n  Bound result 2368\n  Bound result 2146\n  Bound result 8\n  Bound result 2\n  Bound result 63\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.41s (3.41s CPU time)\n\nRan 1 test for test/FurnitureInvariant.t.sol:FurnitureInvariantTest\n[PASS]\nFurnitureInvariantTest invariants:\n[PASS] invariant_BalancesAndSupplyMatchGhosts\n[PASS] invariant_FrozenMetadataNeverChangesAndRoyaltyIsBounded\n[PASS] invariant_OwnerNeverHoldsOrDestroysAnything\n FurnitureInvariantTest invariants (runs: 96, calls: 7680, reverts: 0)\n\n╭------------------+--------------------------+-------+---------+----------╮\n| Contract         | Selector                 | Calls | Reverts | Discards |\n+==========================================================================+\n| FurnitureHandler | mint                     | 1165  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | operatorBatchTransfer    | 1068  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | ownerMetadata            | 1112  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | ownerTriesToSeize        | 1061  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | revokeApproval           | 1112  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | strangerCannotAdminister | 1075  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | transfer                 | 1087  | 0       | 0        |\n╰------------------+--------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 5\n  Bound result 14\n  Bound result 1\n  Bound result 14\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 5\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 13\n  Bound result 14\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 9\n  Bound result 0\n  Bound result 10\n  Bound result 7\n  Bound result 8\n  Bound result 3\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 8\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 6\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 9\n  Bound result 0\n  Bound result 4\n  Bound result 14\n  Bound result 16\n  Bound result 14\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 4\n  Bound result 0\n  Bound result 6\n  Bound result 1008\n  Bound result 3\n  Bound result 0\n  Bound result 7\n  Bound result 0\n  Bound result 2\n  Bound result 11\n  Bound result 1\n  Bound result 0\n  Bound result 9\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 9\n  Bound result 6\n  Bound result 20\n  Bound result 14\n  Bound result 13\n  Bound result 14\n  Bound result 3\n  Bound result 4\n  Bound result 2\n  Bound result 7\n  Bound result 15\n  Bound result 10\n  Bound result 882\n  Bound result 5\n  Bound result 2\n  Bound result 12\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 10\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 9\n  Bound result 12\n  Bound result 7\n  Bound result 24\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 8\n  Bound result 0\n  Bound result 2\n  Bound result 7\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 599\n  Bound result 14\n  Bound result 0\n  Bound result 1\n  Bound result 9\n  Bound result 3\n  Bound result 0\n  Bound result 5\n  Bound result 0\n  Bound result 2\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 9.12s (9.12s CPU time)\n\nRan 13 test suites in 9.13s (19.51s CPU time): 104 tests passed, 0 failed, 0 skipped (104 total tests)\n","passed":true},{"durationMs":131,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OGClubFarmVault.acceptOwnership()\",\"OGClubFarmVault.cancelSeason(uint256)\",\"OGClubFarmVault.claim(uint256,address,uint256,bytes32[])\",\"OGClubFarmVault.proposeSeason(bytes32,uint256)\",\"OGClubFarmVault.releaseSeason(uint256)\",\"OGClubFarmVault.renounceOwnership()\",\"OGClubFarmVault.transferOwnership(address)\",\"OGClubFurniture.acceptOwnership()\",\"OGClubFurniture.activateMinter(address)\",\"OGClubFurniture.cancelMinter(address)\",\"OGClubFurniture.freezeMetadata()\",\"OGClubFurniture.grantMinter(address)\",\"OGClubFurniture.mintBatch(address,uint256[],uint256[])\",\"OGClubFurniture.renounceOwnership()\",\"OGClubFurniture.revokeMinter(address)\",\"OGClubFurniture.safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\",\"OGClubFurniture.safeTransferFrom(address,address,uint256,uint256,bytes)\",\"OGClubFurniture.setApprovalForAll(address,bool)\",\"OGClubFurniture.setBaseURI(string)\",\"OGClubFurniture.setRoyalty(address,uint96)\",\"OGClubFurniture.transferOwnership(address)\",\"OGClubRaffle.acceptOwnership()\",\"OGClubRaffle.cancelRaffle(uint256)\",\"OGClubRaffle.claim(uint256,uint256,(uint256,uint256)[])\",\"OGClubRaffle.claimTo(uint256,uint256,(uint256,uint256)[],address)\",\"OGClubRaffle.commitDraw(uint256)\",\"OGClubRaffle.createRaffle(uint256,uint256,(uint8,uint256,uint256,(uint256,uint256)[])[])\",\"OGClubRaffle.draw(uint256,bytes)\",\"OGClubRaffle.enter(uint256,uint256,uint256)\",\"OGClubRaffle.renounceOwnership()\",\"OGClubRaffle.transferOwnership(address)\",\"OGClubStaking.acceptOwnership()\",\"OGClubStaking.activateSpender(address)\",\"OGClubStaking.cancelSpender(address)\",\"OGClubStaking.grantSpender(address)\",\"OGClubStaking.renounceOwnership()\",\"OGClubStaking.revokeSpender(address)\",\"OGClubStaking.spendPoints(address,uint256)\",\"OGClubStaking.stake(uint256)\",\"OGClubStaking.transferOwnership(address)\",\"OGClubStaking.unstake(uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":126,\"README.md\":290,\"VENDOR.md\":13,\"foundry.toml\":22,\"launch.json\":44,\"script/Deploy.s.sol\":59,\"script/encode_header.py\":82,\"src/OGClubFarmVault.sol\":115,\"src/OGClubFurniture.sol\":138,\"src/OGClubRaffle.sol\":357,\"src/OGClubStaking.sol\":176,\"src/libraries/BlockHeader.sol\":70,\"src/libraries/Permutation.sol\":30,\"src/mocks/MockOG.sol\":21,\"test/BlockHeader.t.sol\":144,\"test/Deployment.t.sol\":117,\"test/FurnitureInvariant.t.sol\":248,\"test/Gas.t.sol\":138,\"test/OGClubFarmVault.t.sol\":309,\"test/OGClubFurniture.t.sol\":362,\"test/OGClubRaffle.t.sol\":537,\"test/OGClubStaking.t.sol\":280,\"test/Permutation.t.sol\":49,\"test/RoleLifecycle.t.sol\":146,\"test/StakingInvariant.t.sol\":153,\"test/VaultInvariant.t.sol\":156,\"test/fixtures/MainnetHeaders.sol\":32,\"test/fixtures/SOURCES.md\":74,\"test/fixtures/SepoliaHeader.sol\":14,\"test/fixtures/mainnet-cancun.json\":24,\"test/fixtures/mainnet-prague.json\":25,\"test/fixtures/mainnet-shanghai.json\":21,\"test/fixtures/sepolia-11921684.json\":27,\"test/helpers/HeaderBuilder.sol\":48,\"test/helpers/RaffleTestBase.sol\":98,\"test/helpers/TokenMocks.sol\":93,\"test/test_encode_header.py\":65,\"test/test_launch.py\":47},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"94de2a823fd09f60c7f64e03a015e0f58a6f103225ed5e5937ffc9056a70c9ee","verifiedTreeHash":"216b2a4958542121a2e536a731fbbc2f90c6d8ef","verifierVersion":"0.1.0+745c1db4"},{"checks":[{"durationMs":12441,"exitCode":0,"name":"build","output":"Compiling 77 files with Solc 0.8.26\nSolc 0.8.26 finished in 12.28s\nCompiler run successful!\n","passed":true},{"durationMs":68952,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 6 tests for test/TokenFailureAtomicity.t.sol:TokenFailureAtomicityTest\n[PASS] test_FalseReturningPayoutPreservesEarlierClaimsAndAllReservations() (gas: 728445)\n[PASS] test_OneWeiExitDoesNotCallTheZeroNetRecipientTransfer() (gas: 294703)\n[PASS] test_PackedStakeOverflowRestoresTransferAndPendingPointState() (gas: 487274)\n[PASS] test_SecondUnstakeTransferFailureRestoresVaultFeeAndAccrualCheckpoint() (gas: 612686)\n[PASS] test_SenderSurchargeCannotConsumeAnotherSeasonsReservation() (gas: 1561673)\n[PASS] test_VaultAcceptsNoReturnTokensAndPaysOnlyTheProvenAccount() (gas: 644163)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 38.02ms (2.36ms CPU time)\n\nRan 3 tests for test/Permutation.t.sol:PermutationTest\n[PASS] testFuzz_LargeDomainsInRangeAndDistinct(uint48,uint48,uint48,bytes32) (runs: 256, μ: 20208, ~: 18133)\nLogs:\n  Bound result 4950\n\n[PASS] testFuzz_SmallDomainsAreBijections(uint8,bytes32) (runs: 256, μ: 620410, ~: 380397)\nLogs:\n  Bound result 5\n\n[PASS] test_InvalidDomainAndIndexRejected() (gas: 211485)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 237.20ms (246.45ms CPU time)\n\nRan 16 tests for test/OGClubFurniture.t.sol:FurnitureTest\n[PASS] testFuzz_AfterFirstMintMustWaitAndAnyoneCanActivate(uint32) (runs: 256, μ: 596121, ~: 595918)\nLogs:\n  Bound result 780\n\n[PASS] testFuzz_EveryGrantAfterTheFirstWaitsSevenDays(address,address,uint32) (runs: 256, μ: 169386, ~: 169450)\n[PASS] test_AllOwnerFunctionsProtected() (gas: 227178)\n[PASS] test_CancelStopsActivationEvenAfterDeadline() (gas: 394671)\n[PASS] test_IdentityInterfacesMintAndSupply() (gas: 448761)\n[PASS] test_InvalidAddressesAndBatchLengths() (gas: 3967)\n[PASS] test_MetadataFreezesPermanently() (gas: 195226)\n[PASS] test_NoOwnerSeizureOrBurn() (gas: 418561)\n[PASS] test_OnlyTheFirstGrantIsImmediateEvenBeforeAnyMint() (gas: 546001)\n[PASS] test_OwnershipTwoStepAndRenounce() (gas: 244214)\n[PASS] test_RegrantingTheRevokedFirstMinterWaitsWithZeroSupply() (gas: 569038)\n[PASS] test_RejectedGrantDoesNotSpendTheBootstrap() (gas: 173991)\n[PASS] test_ReproposalRestartsDelayAndCancelDoesNotRevokeExistingRole() (gas: 457168)\n[PASS] test_RevokeIsImmediateClearsProposalsAndRegrantWaitsAgain() (gas: 535486)\n[PASS] test_RoyaltyDefaultAndLimits() (gas: 161390)\n[PASS] test_ZeroAddressesAndLegacyMinterSelectorCannotGrant() (gas: 340672)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 259.31ms (274.99ms CPU time)\n\nRan 23 tests for test/OGClubRaffle.t.sol:RaffleTest\n[PASS] testFuzz_ExactlyMinPrizesAndTicketsWinWithNoDuplicateTicket(uint8,uint8,bytes32) (runs: 256, μ: 1618560, ~: 1120002)\nLogs:\n  Bound result 9\n  Bound result 8\n\n[PASS] testFuzz_NoticeAlwaysMeasuredFromCreation(uint32) (runs: 256, μ: 241106, ~: 240936)\nLogs:\n  Bound result 780\n\n[PASS] test_ClaimToCannotRedirectAnotherWalletInTheSameBatch() (gas: 1239609)\n[PASS] test_ContractWalletCanRedirectButNobodyElseCan() (gas: 2015153)\n[PASS] test_DrawHeaderAndTargetExactBoundaries() (gas: 641712)\n[PASS] test_DuplicateWithinBatchRollsBackEverythingAndBitmapCrossesWords() (gas: 937264)\n[PASS] test_EntryFailureRollsBackRangesCapsAndPoints() (gas: 833603)\n[PASS] test_EntryWindowAndWalletCapExactBoundaries() (gas: 808341)\n[PASS] test_HugeTicketAndPrizeCountsDoNotRequireIterationToDrawOrClaim() (gas: 925425)\n[PASS] test_InvalidConfigurationPoolsLinesAndTickets() (gas: 941928)\n[PASS] test_Maximum32PoolsAnd128PrizeLines() (gas: 15557738)\n[PASS] test_MultiItemPoolMintsExactQuantitiesIncludingDuplicateAndZeroIds() (gas: 2370129)\n[PASS] test_NoticeExactBoundariesAndCancellation() (gas: 540021)\n[PASS] test_OwnerCannotModifyTermsPauseOrCancelStartedRaffle() (gas: 450829)\n[PASS] test_ReceiverCannotReenterEitherClaimPath() (gas: 1991045)\n[PASS] test_RejectingWalletDoesNotBlockOtherWinnersAndEmptyClaimRejected() (gas: 2030167)\n[PASS] test_RetargetOnlyAt257AndOldHeaderCannotDrawNewTarget() (gas: 560166)\n[PASS] test_RevokedMinterClaimIsRetryableAndDoesNotReroll() (gas: 1017518)\n[PASS] test_TicketPriceMultiplicationOverflowDoesNotSpendOrRecordEntry() (gas: 370843)\n[PASS] test_UnlimitedCapIsPerPoolAndRangesStayContiguous() (gas: 878602)\n[PASS] test_UnsoldPrizesAreRandomPositionsNotAlwaysTheTail() (gas: 3336643)\n[PASS] test_WrongKEntryAndDoubleClaimsRevertAtomically() (gas: 1332250)\n[PASS] test_WrongNumberInAuthenticatedHeaderRejected() (gas: 365306)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 324.84ms (451.54ms CPU time)\n\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\nRan 6 tests for test/Gas.t.sol:GasTest\n[PASS] test_GasClaimOne() (gas: 954101)\nLogs:\n  Claim one win / fresh furniture wallet\n  Cancun call gas: 160885\n  New persistent slots: 4\n  EIP-8037 state gas: 391680\n  EIP-8037 storage-repriced call gas: 472565\n\n[PASS] test_GasClaimTen() (gas: 2860761)\nLogs:\n  Claim ten distinct items / fresh furniture wallet\n  Cancun call gas: 816170\n  New persistent slots: 22\n  EIP-8037 state gas: 2154240\n  EIP-8037 storage-repriced call gas: 2530410\n\n[PASS] test_GasDraw() (gas: 418645)\nLogs:\n  Draw / 23-field synthetic header\n  Cancun call gas: 74312\n  New persistent slots: 1\n  EIP-8037 state gas: 97920\n  EIP-8037 storage-repriced call gas: 152232\n\n[PASS] test_GasEnter() (gas: 558676)\nLogs:\n  First entry / ten tickets / first points checkpoint\n  Cancun call gas: 155364\n  New persistent slots: 4\n  EIP-8037 state gas: 391680\n  EIP-8037 storage-repriced call gas: 467044\n\n[PASS] test_GasFirstStake() (gas: 200138)\nLogs:\n  First-ever stake / fresh staker\n  Cancun call gas: 120547\n  New persistent slots: 3\n  EIP-8037 state gas: 293760\n  EIP-8037 storage-repriced call gas: 354307\n\n[PASS] test_GasUnstake() (gas: 308132)\nLogs:\n  Partial unstake / first fee / first checkpoint\n  Cancun call gas: 110662\n  New persistent slots: 2\n  EIP-8037 state gas: 195840\n  EIP-8037 storage-repriced call gas: 266502\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 389.56ms (67.67ms CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_ConstructorsDoNotCallDependenciesOrAssignFactoryOwner() (gas: 45432)\n[PASS] test_InvalidConfigurationAndConstructorBounds() (gas: 8014)\n[PASS] test_MockIsDeliberatelyUnlimitedTestnetOnly() (gas: 77458)\n[PASS] test_SepoliaDeploymentAndOwnerSetup() (gas: 34864668)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 396.54ms (90.63ms CPU time)\n\nRan 16 tests for test/OGClubFarmVault.t.sol:FarmVaultTest\n[PASS] testFuzz_ReserveCapAndClaimConservation(uint96,uint96) (runs: 256, μ: 1352248, ~: 1352235)\nLogs:\n  Bound result 1001\n  Bound result 335\n\n[PASS] test_CancelBeforeOpenOnlyReleasesReserveWithoutTransferring() (gas: 561805)\n[PASS] test_ClaimLastSecondBeforeExpirationAndPartialRelease() (gas: 397391)\n[PASS] test_DelayExactBoundaryAndPermissionlessClaimPaidToAccountOnly() (gas: 442808)\n[PASS] test_FailedTokenTransferRestoresClaimAndReservations() (gas: 727404)\n[PASS] test_HalfCapUsesOnlyUnreservedBalanceAndFloorsOddWei() (gas: 472822)\n[PASS] test_InvalidRecipientsAndZeroAllocation() (gas: 482033)\n[PASS] test_InvalidSeasonRootAndTotal() (gas: 164553)\n[PASS] test_OnlyOwnerCanProposeCancelAndNoSweepOrApprovalOrPause() (gas: 165634)\n[PASS] test_OwnerCallbackCannotReserveAgainstAnInFlightPayout() (gas: 625341)\n[PASS] test_OwnershipHandoverPreservesSeasons() (gas: 415758)\n[PASS] test_ProofRejectsWrongAccountAmountSeasonAndSingleHash() (gas: 898876)\n[PASS] test_ProposalIntervalAtExactBoundaryIncludingAfterCancel() (gas: 441729)\n[PASS] test_ReleaseExactly90DaysAfterOpeningAndNeverWithdrawsTokens() (gas: 562741)\n[PASS] test_TokenCallbackCannotClaimTwice() (gas: 521104)\n[PASS] test_TotalBudgetCapsEvenInconsistentMerkleTree() (gas: 355026)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 406.26ms (407.23ms CPU time)\n\nRan 10 tests for test/BlockHeader.t.sol:BlockHeaderTest\n[PASS] testFuzz_AnyMalformedInputRevertsWithCustomError(bytes) (runs: 256, μ: 32405, ~: 32037)\n[PASS] testFuzz_ArbitraryTrailingFieldCount(uint8,uint256,bytes32) (runs: 256, μ: 92389, ~: 76737)\nLogs:\n  Bound result 50\n\n[PASS] test_MalformedAuthenticatedHeaderCannotMint() (gas: 321913)\n[PASS] test_MalformedRLPBoundsAndCanonicalLengths() (gas: 147737)\n[PASS] test_MissingFieldsAndInvalidNumberOrMixHash() (gas: 237524)\n[PASS] test_RealMainnetCancunHeader() (gas: 543993)\n[PASS] test_RealMainnetPragueHeader() (gas: 547036)\n[PASS] test_RealMainnetShanghaiHeader() (gas: 538038)\n[PASS] test_RealSepoliaHeaderWithAccessListHashAndSlotNumber() (gas: 550588)\n[PASS] test_ZeroNumberAndZeroMixHashAreValidRLP() (gas: 40712)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 446.61ms (126.12ms CPU time)\n\nRan 7 tests for test/RoleLifecycle.t.sol:RoleLifecycleTest\n[PASS] testFuzz_ExpiredProposalsCannotActivateOrCancel(uint32) (runs: 256, μ: 558669, ~: 558520)\nLogs:\n  Bound result 780\n\n[PASS] test_ActivationAtMaturityAndLastSecond() (gas: 512088)\n[PASS] test_CancelRevokeRegrantAndReproposal() (gas: 800981)\n[PASS] test_InvalidGrantDoesNotSpendBootstrapAndZeroAddressesRejected() (gas: 147761)\n[PASS] test_OnlyOwnerProposesCancelsAndRevokes() (gas: 406632)\n[PASS] test_OwnershipHandoverDoesNotResetBootstrapAndRenunciationDoesNotBlockActivation() (gas: 568368)\n[PASS] test_SpenderLastSecondActivates() (gas: 378503)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 445.67ms (443.32ms CPU time)\n\nRan 15 tests for test/OGClubStaking.t.sol:StakingTest\n[PASS] testFuzz_CheckpointFrequencyDoesNotChangePoints(uint96,uint32,uint8) (runs: 256, μ: 1106774, ~: 801119)\nLogs:\n  Bound result 299\n  Bound result 247\n  Bound result 2\n\n[PASS] testFuzz_FeeRoundsUpAndConservesBalance(uint96) (runs: 256, μ: 282800, ~: 283076)\nLogs:\n  Bound result 13702691596\n\n[PASS] testFuzz_WholeTokenAccrualAcrossSupportedDecimals(uint8,uint96,uint32) (runs: 256, μ: 1219235, ~: 1219445)\nLogs:\n  Bound result 3\n  Bound result 132378796646027\n  Bound result 15161804\n\n[PASS] test_AccrueBeforeBalanceChangesAndNoLock() (gas: 427758)\n[PASS] test_CheckpointsPreserveSubWeiAccrualAndFullExitFraction() (gas: 1366740)\n[PASS] test_DecimalsReadOnFirstUseAndNormalizeWholeTokens() (gas: 2190760)\n[PASS] test_DonationsNeitherCreateStakeNorAwardPoints() (gas: 343342)\n[PASS] test_ExactContinuousAccrualAtBoundariesAndSpend() (gas: 299793)\n[PASS] test_FeeOnTransferCreditsOnlyReceivedAndCannotInflatePoints() (gas: 381142)\n[PASS] test_InvalidAmountsUnauthorizedSpendAndOwnerCannotTouchStakes() (gas: 406963)\n[PASS] test_MaximumPackedBalanceAndRateAccrueWithoutIntermediateOverflow() (gas: 448069)\n[PASS] test_NoReturnAndFalseReturnTokens() (gas: 734103)\n[PASS] test_TinyUnstakesAlwaysPayFee() (gas: 360201)\n[PASS] test_TokenCallbackCannotSpendOrReenterStakeOrUnstake() (gas: 685618)\n[PASS] test_ZeroReceiptAndSenderSideFeeRevertAtomically() (gas: 554565)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 444.27ms (896.37ms CPU time)\n\nRan 6 tests for test/RaffleAtomicity.t.sol:RaffleAtomicityTest\n[PASS] testFuzz_MultiItemClaimsCanBeShuffledAndFragmented(uint8[4],bytes32) (runs: 512, μ: 3655177, ~: 3551656)\nLogs:\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 3\n\n[PASS] test_ClaimBitmapIsIndependentAcrossRafflesAndPools() (gas: 2082130)\n[PASS] test_LateInvalidEntryRollsBackAnEarlierWalletMint() (gas: 1264278)\n[PASS] test_LateInvalidPoolCreationDoesNotLeaveRaffleOrPrizeStorage() (gas: 507505)\n[PASS] test_LateReceiverRejectionRollsBackPreviouslyMintedWalletGroup() (gas: 2144305)\n[PASS] test_PrizeLimitAppliesToSumAcrossLinesAndRollbackAllowsReuse() (gas: 498160)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 445.46ms (451.32ms CPU time)\n\nRan 1 test for test/VaultInvariant.t.sol:VaultInvariantTest\n[PASS] invariant_VaultAlwaysCoversReservationsAndOnlyClaimsMoveTokens() (runs: 128, calls: 8192, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | advance  | 1307  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | cancel   | 1354  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | claim    | 1366  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1377  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | propose  | 1436  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | release  | 1352  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 1000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 604800\n  Bound result 100000000000000000000\n  Bound result 259200\n  Bound result 345600\n  Bound result 100000000000000000000\n  Bound result 8035200\n  Bound result 3063565111\n  Bound result 855\n  Bound result 4716\n  Bound result 210607787\n  Bound result 240\n  Bound result 20525562795\n  Bound result 12125\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 7798\n  Bound result 5984\n  Bound result 2947\n  Bound result 3689274\n  Bound result 7628737\n  Bound result 400\n  Bound result 247\n  Bound result 2930\n  Bound result 1001\n  Bound result 107477463\n  Bound result 11055\n  Bound result 43\n  Bound result 8394869\n  Bound result 556\n  Bound result 3452324\n  Bound result 2246\n  Bound result 2755\n  Bound result 8394869\n  Bound result 6423\n  Bound result 1415071841494791321\n  Bound result 1741832\n  Bound result 2652\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.37s (2.36s CPU time)\n\nRan 1 test for test/StakingInvariant.t.sol:StakingInvariantTest\n[PASS]\nStakingInvariantTest invariants:\n[PASS] invariant_PointsAppearOnlyByTimeWeightedAccrualAndLeaveOnlyBySpending\n[PASS] invariant_StakingBalanceEqualsAllStakes\n StakingInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| StakingHandler | advance           | 1684  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | spend             | 1645  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | stake             | 1650  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unauthorizedSpend | 1582  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unstake           | 1631  | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10000000000000000000\n  Bound result 86400\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 6353\n  Bound result 4087\n  Bound result 2999\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 1296743294243\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 2852\n  Bound result 681321223797248079663\n  Bound result 0\n  Bound result 0\n  Bound result 341\n  Bound result 3\n  Bound result 8\n  Bound result 4034017728\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 0\n  Bound result 718875\n  Bound result 6390\n  Bound result 1001\n  Bound result 1001\n  Bound result 136048409024462934820\n  Bound result 456\n  Bound result 255\n  Bound result 1406\n  Bound result 431\n  Bound result 514264337593543950335\n  Bound result 771998\n  Bound result 149689680\n  Bound result 700\n  Bound result 2645\n  Bound result 1264811664\n  Bound result 514264337593543950335\n  Bound result 1583089378\n  Bound result 831059\n  Bound result 33\n  Bound result 1001\n  Bound result 5768\n  Bound result 2478893114\n  Bound result 18324\n  Bound result 1131\n  Bound result 514264337593543950335\n  Bound result 215\n  Bound result 771998\n  Bound result 10000000040340181\n  Bound result 2481\n  Bound result 4088\n  Bound result 787\n  Bound result 4176\n  Bound result 8857776364506205618791\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.18s (3.17s CPU time)\n\nRan 1 test for test/StakingInvariant.t.sol:FeeStakingInvariantTest\n[PASS]\nFeeStakingInvariantTest invariants:\n[PASS] invariant_PointsAppearOnlyByTimeWeightedAccrualAndLeaveOnlyBySpending\n[PASS] invariant_StakingBalanceEqualsAllStakes\n FeeStakingInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| StakingHandler | advance           | 1684  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | spend             | 1645  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | stake             | 1650  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unauthorizedSpend | 1582  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unstake           | 1631  | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10000000000000000000\n  Bound result 86400\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 6327\n  Bound result 4088\n  Bound result 2998\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 1296743294243\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 3097\n  Bound result 128\n  Bound result 0\n  Bound result 0\n  Bound result 261\n  Bound result 3\n  Bound result 8\n  Bound result 4202047189\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 1158\n  Bound result 1851\n  Bound result 63\n  Bound result 1001\n  Bound result 1001\n  Bound result 225\n  Bound result 5760\n  Bound result 255\n  Bound result 2162\n  Bound result 431\n  Bound result 514264337593543950335\n  Bound result 771998\n  Bound result 149689680\n  Bound result 700\n  Bound result 61\n  Bound result 2273\n  Bound result 514264337593543950335\n  Bound result 491\n  Bound result 831059\n  Bound result 33\n  Bound result 1001\n  Bound result 312\n  Bound result 188\n  Bound result 18324\n  Bound result 1271\n  Bound result 514264337593543950335\n  Bound result 215\n  Bound result 771998\n  Bound result 1001\n  Bound result 2635\n  Bound result 4689\n  Bound result 3074\n  Bound result 115330149\n  Bound result 22575087455250124682706\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.25s (3.23s CPU time)\n\nRan 1 test for test/FurnitureInvariant.t.sol:FurnitureInvariantTest\n[PASS]\nFurnitureInvariantTest invariants:\n[PASS] invariant_BalancesAndSupplyMatchGhosts\n[PASS] invariant_FrozenMetadataNeverChangesAndRoyaltyIsBounded\n[PASS] invariant_OwnerNeverHoldsOrDestroysAnything\n FurnitureInvariantTest invariants (runs: 96, calls: 7680, reverts: 0)\n\n╭------------------+--------------------------+-------+---------+----------╮\n| Contract         | Selector                 | Calls | Reverts | Discards |\n+==========================================================================+\n| FurnitureHandler | mint                     | 1165  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | operatorBatchTransfer    | 1068  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | ownerMetadata            | 1112  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | ownerTriesToSeize        | 1061  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | revokeApproval           | 1112  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | strangerCannotAdminister | 1075  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | transfer                 | 1087  | 0       | 0        |\n╰------------------+--------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 5\n  Bound result 14\n  Bound result 5\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 17\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 14\n  Bound result 14\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 14\n  Bound result 0\n  Bound result 5\n  Bound result 0\n  Bound result 20\n  Bound result 14\n  Bound result 10\n  Bound result 7\n  Bound result 0\n  Bound result 7\n  Bound result 14\n  Bound result 0\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 27\n  Bound result 9\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 13\n  Bound result 13\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 431\n  Bound result 1\n  Bound result 14\n  Bound result 14\n  Bound result 7\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 8\n  Bound result 1008\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 19\n  Bound result 14\n  Bound result 1\n  Bound result 1\n  Bound result 14\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 4\n  Bound result 39\n  Bound result 4\n  Bound result 3\n  Bound result 19\n  Bound result 10\n  Bound result 4\n  Bound result 7\n  Bound result 17\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 8\n  Bound result 11\n  Bound result 17\n  Bound result 7\n  Bound result 926\n  Bound result 22\n  Bound result 0\n  Bound result 1\n  Bound result 11\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 10\n  Bound result 8\n  Bound result 2\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 14\n  Bound result 0\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 12\n  Bound result 1\n  Bound result 5\n  Bound result 8\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 8.33s (8.31s CPU time)\n\nRan 1 test for test/FeeFlowInvariant.t.sol:FeeFlowInvariantTest\n[PASS]\nFeeFlowInvariantTest invariants:\n[PASS] invariant_EachReservationEqualsUnpaidAllocationsOfAnOpenSeason\n[PASS] invariant_PointsConservedThroughPartialExitsClaimsAndRestakes\n[PASS] invariant_TokensConservedAcrossStakeFeeVaultPayoutAndBurn\n FeeFlowInvariantTest invariants (runs: 128, calls: 12288, reverts: 0)\n\n╭----------------+-----------+-------+---------+----------╮\n| Contract       | Selector  | Calls | Reverts | Discards |\n+=========================================================+\n| FeeFlowHandler | advance   | 1114  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | badProof  | 1152  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | cancel    | 1035  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | claim     | 1101  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | exit      | 1116  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | overspend | 1119  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | propose   | 1201  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | release   | 1095  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | spend     | 1053  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | stake     | 1141  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | unstake   | 1161  | 0       | 0        |\n╰----------------+-----------+-------+---------+----------╯\n\nLogs:\n  Bound result 100000000000\n  Bound result 100000000000\n  Bound result 100000000000\n  Bound result 100000000000\n  Bound result 50000000000\n  Bound result 100000000\n  Bound result 604800\n  Bound result 100000000\n  Bound result 259200\n  Bound result 1000000000000000000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 40000000\n  Bound result 50000000000\n  Bound result 1001\n  Bound result 300290\n  Bound result 1001\n  Bound result 42343950332\n  Bound result 143\n  Bound result 900\n  Bound result 98424119001\n  Bound result 31\n  Bound result 14169\n  Bound result 42343950332\n  Bound result 1016\n  Bound result 99999998999\n  Bound result 917\n  Bound result 100000014169\n  Bound result 11791\n  Bound result 5510\n  Bound result 7238\n  Bound result 1001\n  Bound result 678228\n  Bound result 12052\n  Bound result 851908006033\n  Bound result 5933738848164753961763878\n  Bound result 696283937961\n  Bound result 34044635901\n  Bound result 1001\n  Bound result 8868\n  Bound result 2722610226\n  Bound result 257675\n  Bound result 3887\n  Bound result 12085\n  Bound result 67132642680\n  Bound result 1001\n  Bound result 884996004945\n  Bound result 1294488\n  Bound result 4086075263\n  Bound result 1439\n  Bound result 9574\n  Bound result 956514\n  Bound result 1202988\n  Bound result 49\n  Bound result 569141\n  Bound result 952\n  Bound result 697859806296\n  Bound result 9574\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 11.99s (11.97s CPU time)\n\nRan 1 test for test/FeeFlowInvariant.t.sol:TaxedFeeFlowInvariantTest\n[PASS]\nTaxedFeeFlowInvariantTest invariants:\n[PASS] invariant_EachReservationEqualsUnpaidAllocationsOfAnOpenSeason\n[PASS] invariant_PointsConservedThroughPartialExitsClaimsAndRestakes\n[PASS] invariant_TokensConservedAcrossStakeFeeVaultPayoutAndBurn\n TaxedFeeFlowInvariantTest invariants (runs: 128, calls: 12288, reverts: 0)\n\n╭----------------+-----------+-------+---------+----------╮\n| Contract       | Selector  | Calls | Reverts | Discards |\n+=========================================================+\n| FeeFlowHandler | advance   | 1114  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | badProof  | 1152  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | cancel    | 1035  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | claim     | 1101  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | exit      | 1116  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | overspend | 1119  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | propose   | 1201  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | release   | 1095  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | spend     | 1053  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | stake     | 1141  | 0       | 0        |\n|----------------+-----------+-------+---------+----------|\n| FeeFlowHandler | unstake   | 1161  | 0       | 0        |\n╰----------------+-----------+-------+---------+----------╯\n\nLogs:\n  Bound result 100000000000\n  Bound result 100000000000\n  Bound result 100000000000\n  Bound result 100000000000\n  Bound result 50000000000\n  Bound result 100000000\n  Bound result 604800\n  Bound result 100000000\n  Bound result 259200\n  Bound result 1000000000000000000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 1296000\n  Bound result 40000000\n  Bound result 92500000000\n  Bound result 1001\n  Bound result 300290\n  Bound result 755193616\n  Bound result 1001\n  Bound result 113238208964\n  Bound result 6607\n  Bound result 900\n  Bound result 31\n  Bound result 2277\n  Bound result 146490149676\n  Bound result 92500000000\n  Bound result 917\n  Bound result 5735\n  Bound result 7446\n  Bound result 1001\n  Bound result 678228\n  Bound result 167\n  Bound result 944639575335\n  Bound result 1338205303289190886644186\n  Bound result 240920621437\n  Bound result 14005\n  Bound result 1001\n  Bound result 9312\n  Bound result 2302988626\n  Bound result 257675\n  Bound result 4125\n  Bound result 11650\n  Bound result 925000000\n  Bound result 1001\n  Bound result 315351581973\n  Bound result 196402\n  Bound result 9511\n  Bound result 9575\n  Bound result 956514\n  Bound result 1202988\n  Bound result 49\n  Bound result 334616\n  Bound result 877\n  Bound result 874647218651\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 12.15s (12.13s CPU time)\n\nRan 1 test for test/RaffleSequenceInvariant.t.sol:RaffleSequenceInvariantTest\n[PASS]\nRaffleSequenceInvariantTest invariants:\n[PASS] invariant_ClaimBitsMatchMintReceiptsAndNeverMintUnawardedPrizes\n[PASS] invariant_FinalizedDrawsAndTermsNeverChange\n[PASS] invariant_PointsSpentExactlyMatchAcceptedRanges\n RaffleSequenceInvariantTest invariants (runs: 128, calls: 12288, reverts: 0)\n\n╭-----------------------+----------+-------+---------+----------╮\n| Contract              | Selector | Calls | Reverts | Discards |\n+===============================================================+\n| RaffleSequenceHandler | advance  | 1608  | 0       | 0        |\n|-----------------------+----------+-------+---------+----------|\n| RaffleSequenceHandler | badClaim | 1489  | 0       | 0        |\n|-----------------------+----------+-------+---------+----------|\n| RaffleSequenceHandler | cancel   | 1572  | 0       | 0        |\n|-----------------------+----------+-------+---------+----------|\n| RaffleSequenceHandler | claim    | 1542  | 0       | 0        |\n|-----------------------+----------+-------+---------+----------|\n| RaffleSequenceHandler | commit   | 1543  | 0       | 0        |\n|-----------------------+----------+-------+---------+----------|\n| RaffleSequenceHandler | create   | 1518  | 0       | 0        |\n|-----------------------+----------+-------+---------+----------|\n| RaffleSequenceHandler | draw     | 1543  | 0       | 0        |\n|-----------------------+----------+-------+---------+----------|\n| RaffleSequenceHandler | enter    | 1473  | 0       | 0        |\n╰-----------------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 86400\n  Bound result 0\n  Bound result 0\n  Bound result 5\n  Bound result 5\n  Bound result 2\n  Bound result 1\n  Bound result 172800\n  Bound result 0\n  Bound result 172800\n  Bound result 0\n  Bound result 172800\n  Bound result 0\n  Bound result 1\n  Bound result 86400\n  Bound result 0\n  Bound result 4\n  Bound result 128\n  Bound result 34\n  Bound result 9382\n  Bound result 1\n  Bound result 55\n  Bound result 225\n  Bound result 9\n  Bound result 0\n  Bound result 7\n  Bound result 77920\n  Bound result 259\n  Bound result 239\n  Bound result 171241\n  Bound result 8\n  Bound result 0\n  Bound result 172786\n  Bound result 189\n  Bound result 858\n  Bound result 0\n  Bound result 6\n  Bound result 0\n  Bound result 43200\n  Bound result 128\n  Bound result 148831\n  Bound result 32\n  Bound result 6250\n  Bound result 262\n  Bound result 112\n  Bound result 227\n  Bound result 7\n  Bound result 112\n  Bound result 2\n  Bound result 10\n  Bound result 54766\n  Bound result 139\n  Bound result 9804\n  Bound result 29\n  Bound result 10\n  Bound result 131938\n  Bound result 105\n  Bound result 196\n  Bound result 4\n  Bound result 86399\n  Bound result 250\n  Bound result 96\n  Bound result 8\n  Bound result 1\n  Bound result 145\n  Bound result 42\n  Bound result 119\n  Bound result 42\n  Bound result 108\n  Bound result 139755\n  Bound result 151\n  Bound result 45034\n  Bound result 215\n  Bound result 123\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 68.78s (68.76s CPU time)\n\nRan 18 test suites in 68.79s (113.87s CPU time): 119 tests passed, 0 failed, 0 skipped (119 total tests)\n","passed":true},{"durationMs":140,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OGClubFarmVault.acceptOwnership()\",\"OGClubFarmVault.cancelSeason(uint256)\",\"OGClubFarmVault.claim(uint256,address,uint256,bytes32[])\",\"OGClubFarmVault.proposeSeason(bytes32,uint256)\",\"OGClubFarmVault.releaseSeason(uint256)\",\"OGClubFarmVault.renounceOwnership()\",\"OGClubFarmVault.transferOwnership(address)\",\"OGClubFurniture.acceptOwnership()\",\"OGClubFurniture.activateMinter(address)\",\"OGClubFurniture.cancelMinter(address)\",\"OGClubFurniture.freezeMetadata()\",\"OGClubFurniture.grantMinter(address)\",\"OGClubFurniture.mintBatch(address,uint256[],uint256[])\",\"OGClubFurniture.renounceOwnership()\",\"OGClubFurniture.revokeMinter(address)\",\"OGClubFurniture.safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\",\"OGClubFurniture.safeTransferFrom(address,address,uint256,uint256,bytes)\",\"OGClubFurniture.setApprovalForAll(address,bool)\",\"OGClubFurniture.setBaseURI(string)\",\"OGClubFurniture.setRoyalty(address,uint96)\",\"OGClubFurniture.transferOwnership(address)\",\"OGClubRaffle.acceptOwnership()\",\"OGClubRaffle.cancelRaffle(uint256)\",\"OGClubRaffle.claim(uint256,uint256,(uint256,uint256)[])\",\"OGClubRaffle.claimTo(uint256,uint256,(uint256,uint256)[],address)\",\"OGClubRaffle.commitDraw(uint256)\",\"OGClubRaffle.createRaffle(uint256,uint256,(uint8,uint256,uint256,(uint256,uint256)[])[])\",\"OGClubRaffle.draw(uint256,bytes)\",\"OGClubRaffle.enter(uint256,uint256,uint256)\",\"OGClubRaffle.renounceOwnership()\",\"OGClubRaffle.transferOwnership(address)\",\"OGClubStaking.acceptOwnership()\",\"OGClubStaking.activateSpender(address)\",\"OGClubStaking.cancelSpender(address)\",\"OGClubStaking.grantSpender(address)\",\"OGClubStaking.renounceOwnership()\",\"OGClubStaking.revokeSpender(address)\",\"OGClubStaking.spendPoints(address,uint256)\",\"OGClubStaking.stake(uint256)\",\"OGClubStaking.transferOwnership(address)\",\"OGClubStaking.unstake(uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":126,\"README.md\":290,\"VENDOR.md\":13,\"foundry.toml\":22,\"launch.json\":44,\"script/Deploy.s.sol\":59,\"script/encode_header.py\":82,\"src/OGClubFarmVault.sol\":115,\"src/OGClubFurniture.sol\":138,\"src/OGClubRaffle.sol\":357,\"src/OGClubStaking.sol\":176,\"src/libraries/BlockHeader.sol\":70,\"src/libraries/Permutation.sol\":30,\"src/mocks/MockOG.sol\":21,\"test/ADDITIONAL_COVERAGE.md\":53,\"test/BlockHeader.t.sol\":144,\"test/Deployment.t.sol\":117,\"test/FeeFlowInvariant.t.sol\":386,\"test/FurnitureInvariant.t.sol\":248,\"test/Gas.t.sol\":138,\"test/OGClubFarmVault.t.sol\":309,\"test/OGClubFurniture.t.sol\":362,\"test/OGClubRaffle.t.sol\":537,\"test/OGClubStaking.t.sol\":280,\"test/Permutation.t.sol\":49,\"test/RaffleAtomicity.t.sol\":207,\"test/RaffleSequenceInvariant.t.sol\":503,\"test/RoleLifecycle.t.sol\":146,\"test/StakingInvariant.t.sol\":153,\"test/TokenFailureAtomicity.t.sol\":187,\"test/VaultInvariant.t.sol\":156,\"test/fixtures/MainnetHeaders.sol\":32,\"test/fixtures/SOURCES.md\":74,\"test/fixtures/SepoliaHeader.sol\":14,\"test/fixtures/mainnet-cancun.json\":24,\"test/fixtures/mainnet-prague.json\":25,\"test/fixtures/mainnet-shanghai.json\":21,\"test/fixtures/sepolia-11921684.json\":27,\"test/helpers/HeaderBuilder.sol\":48,\"test/helpers/RaffleTestBase.sol\":98,\"test/helpers/TokenMocks.sol\":93,\"test/test_encode_header.py\":65,\"test/test_launch.py\":47},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"9ce19b60fb0b959a769b007fbf46fecc46ffa2bb4025e5cb8cd7b8149b9c1f2f","verifiedTreeHash":"23ec9e1ec81e568e3613b96ccbfca6e7467ca928","verifierVersion":"0.1.0+745c1db4"},{"checks":[{"durationMs":11410,"exitCode":0,"name":"build","output":"Compiling 73 files with Solc 0.8.26\nSolc 0.8.26 finished in 11.20s\nCompiler run successful!\n","passed":true},{"durationMs":9113,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 6 tests for test/Gas.t.sol:GasTest\n[PASS] test_GasClaimOne() (gas: 954101)\nLogs:\n  Claim one win / fresh furniture wallet\n  Cancun call gas: 160885\n  New persistent slots: 4\n  EIP-8037 state gas: 391680\n  EIP-8037 storage-repriced call gas: 472565\n\n[PASS] test_GasClaimTen() (gas: 2860761)\nLogs:\n  Claim ten distinct items / fresh furniture wallet\n  Cancun call gas: 816170\n  New persistent slots: 22\n  EIP-8037 state gas: 2154240\n  EIP-8037 storage-repriced call gas: 2530410\n\n[PASS] test_GasDraw() (gas: 418645)\nLogs:\n  Draw / 23-field synthetic header\n  Cancun call gas: 74312\n  New persistent slots: 1\n  EIP-8037 state gas: 97920\n  EIP-8037 storage-repriced call gas: 152232\n\n[PASS] test_GasEnter() (gas: 558676)\nLogs:\n  First entry / ten tickets / first points checkpoint\n  Cancun call gas: 155364\n  New persistent slots: 4\n  EIP-8037 state gas: 391680\n  EIP-8037 storage-repriced call gas: 467044\n\n[PASS] test_GasFirstStake() (gas: 200138)\nLogs:\n  First-ever stake / fresh staker\n  Cancun call gas: 120547\n  New persistent slots: 3\n  EIP-8037 state gas: 293760\n  EIP-8037 storage-repriced call gas: 354307\n\n[PASS] test_GasUnstake() (gas: 308132)\nLogs:\n  Partial unstake / first fee / first checkpoint\n  Cancun call gas: 110662\n  New persistent slots: 2\n  EIP-8037 state gas: 195840\n  EIP-8037 storage-repriced call gas: 266502\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 57.38ms (22.40ms CPU time)\n\nRan 7 tests for test/RoleLifecycle.t.sol:RoleLifecycleTest\n[PASS] testFuzz_ExpiredProposalsCannotActivateOrCancel(uint32) (runs: 256, μ: 558669, ~: 558520)\nLogs:\n  Bound result 2\n\n[PASS] test_ActivationAtMaturityAndLastSecond() (gas: 512088)\n[PASS] test_CancelRevokeRegrantAndReproposal() (gas: 800981)\n[PASS] test_InvalidGrantDoesNotSpendBootstrapAndZeroAddressesRejected() (gas: 147761)\n[PASS] test_OnlyOwnerProposesCancelsAndRevokes() (gas: 406632)\n[PASS] test_OwnershipHandoverDoesNotResetBootstrapAndRenunciationDoesNotBlockActivation() (gas: 568368)\n[PASS] test_SpenderLastSecondActivates() (gas: 378503)\nWarning: the following cheatcode(s) are deprecated and will be removed in future versions:\n  lastCallGas(): replaced by `lastFrameGas`\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 56.84ms (60.45ms CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_ConstructorsDoNotCallDependenciesOrAssignFactoryOwner() (gas: 45432)\n[PASS] test_InvalidConfigurationAndConstructorBounds() (gas: 8014)\n[PASS] test_MockIsDeliberatelyUnlimitedTestnetOnly() (gas: 77458)\n[PASS] test_SepoliaDeploymentAndOwnerSetup() (gas: 34864668)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 74.09ms (71.37ms CPU time)\n\nRan 3 tests for test/Permutation.t.sol:PermutationTest\n[PASS] testFuzz_LargeDomainsInRangeAndDistinct(uint48,uint48,uint48,bytes32) (runs: 256, μ: 19932, ~: 18133)\nLogs:\n  Bound result 4950\n\n[PASS] testFuzz_SmallDomainsAreBijections(uint8,bytes32) (runs: 256, μ: 637704, ~: 380397)\nLogs:\n  Bound result 5\n\n[PASS] test_InvalidDomainAndIndexRejected() (gas: 211485)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 184.21ms (193.27ms CPU time)\n\nRan 16 tests for test/OGClubFarmVault.t.sol:FarmVaultTest\n[PASS] testFuzz_ReserveCapAndClaimConservation(uint96,uint96) (runs: 256, μ: 1352248, ~: 1352235)\nLogs:\n  Bound result 1001\n  Bound result 335\n\n[PASS] test_CancelBeforeOpenOnlyReleasesReserveWithoutTransferring() (gas: 561805)\n[PASS] test_ClaimLastSecondBeforeExpirationAndPartialRelease() (gas: 397391)\n[PASS] test_DelayExactBoundaryAndPermissionlessClaimPaidToAccountOnly() (gas: 442808)\n[PASS] test_FailedTokenTransferRestoresClaimAndReservations() (gas: 727404)\n[PASS] test_HalfCapUsesOnlyUnreservedBalanceAndFloorsOddWei() (gas: 472822)\n[PASS] test_InvalidRecipientsAndZeroAllocation() (gas: 482033)\n[PASS] test_InvalidSeasonRootAndTotal() (gas: 164553)\n[PASS] test_OnlyOwnerCanProposeCancelAndNoSweepOrApprovalOrPause() (gas: 165634)\n[PASS] test_OwnerCallbackCannotReserveAgainstAnInFlightPayout() (gas: 625341)\n[PASS] test_OwnershipHandoverPreservesSeasons() (gas: 415758)\n[PASS] test_ProofRejectsWrongAccountAmountSeasonAndSingleHash() (gas: 898876)\n[PASS] test_ProposalIntervalAtExactBoundaryIncludingAfterCancel() (gas: 441729)\n[PASS] test_ReleaseExactly90DaysAfterOpeningAndNeverWithdrawsTokens() (gas: 562741)\n[PASS] test_TokenCallbackCannotClaimTwice() (gas: 521104)\n[PASS] test_TotalBudgetCapsEvenInconsistentMerkleTree() (gas: 355026)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 208.77ms (214.87ms CPU time)\n\nRan 10 tests for test/BlockHeader.t.sol:BlockHeaderTest\n[PASS] testFuzz_AnyMalformedInputRevertsWithCustomError(bytes) (runs: 256, μ: 32404, ~: 32037)\n[PASS] testFuzz_ArbitraryTrailingFieldCount(uint8,uint256,bytes32) (runs: 256, μ: 92417, ~: 76569)\nLogs:\n  Bound result 14\n\n[PASS] test_MalformedAuthenticatedHeaderCannotMint() (gas: 321913)\n[PASS] test_MalformedRLPBoundsAndCanonicalLengths() (gas: 147737)\n[PASS] test_MissingFieldsAndInvalidNumberOrMixHash() (gas: 237524)\n[PASS] test_RealMainnetCancunHeader() (gas: 543993)\n[PASS] test_RealMainnetPragueHeader() (gas: 547036)\n[PASS] test_RealMainnetShanghaiHeader() (gas: 538038)\n[PASS] test_RealSepoliaHeaderWithAccessListHashAndSlotNumber() (gas: 550588)\n[PASS] test_ZeroNumberAndZeroMixHashAreValidRLP() (gas: 40712)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 208.98ms (216.50ms CPU time)\n\nRan 15 tests for test/OGClubStaking.t.sol:StakingTest\n[PASS] testFuzz_CheckpointFrequencyDoesNotChangePoints(uint96,uint32,uint8) (runs: 256, μ: 1084689, ~: 716801)\nLogs:\n  Bound result 935257245299\n  Bound result 24203\n  Bound result 20\n\n[PASS] testFuzz_FeeRoundsUpAndConservesBalance(uint96) (runs: 256, μ: 282800, ~: 283076)\nLogs:\n  Bound result 13702691596\n\n[PASS] testFuzz_WholeTokenAccrualAcrossSupportedDecimals(uint8,uint96,uint32) (runs: 256, μ: 1219222, ~: 1219409)\nLogs:\n  Bound result 3\n  Bound result 132378796646027\n  Bound result 15161804\n\n[PASS] test_AccrueBeforeBalanceChangesAndNoLock() (gas: 427758)\n[PASS] test_CheckpointsPreserveSubWeiAccrualAndFullExitFraction() (gas: 1366740)\n[PASS] test_DecimalsReadOnFirstUseAndNormalizeWholeTokens() (gas: 2190760)\n[PASS] test_DonationsNeitherCreateStakeNorAwardPoints() (gas: 343342)\n[PASS] test_ExactContinuousAccrualAtBoundariesAndSpend() (gas: 299793)\n[PASS] test_FeeOnTransferCreditsOnlyReceivedAndCannotInflatePoints() (gas: 381142)\n[PASS] test_InvalidAmountsUnauthorizedSpendAndOwnerCannotTouchStakes() (gas: 406963)\n[PASS] test_MaximumPackedBalanceAndRateAccrueWithoutIntermediateOverflow() (gas: 448069)\n[PASS] test_NoReturnAndFalseReturnTokens() (gas: 734103)\n[PASS] test_TinyUnstakesAlwaysPayFee() (gas: 360201)\n[PASS] test_TokenCallbackCannotSpendOrReenterStakeOrUnstake() (gas: 685618)\n[PASS] test_ZeroReceiptAndSenderSideFeeRevertAtomically() (gas: 554565)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 283.17ms (420.70ms CPU time)\n\nRan 16 tests for test/OGClubFurniture.t.sol:FurnitureTest\n[PASS] testFuzz_AfterFirstMintMustWaitAndAnyoneCanActivate(uint32) (runs: 256, μ: 596126, ~: 595918)\nLogs:\n  Bound result 780\n\n[PASS] testFuzz_EveryGrantAfterTheFirstWaitsSevenDays(address,address,uint32) (runs: 256, μ: 169386, ~: 169450)\n[PASS] test_AllOwnerFunctionsProtected() (gas: 227178)\n[PASS] test_CancelStopsActivationEvenAfterDeadline() (gas: 394671)\n[PASS] test_IdentityInterfacesMintAndSupply() (gas: 448761)\n[PASS] test_InvalidAddressesAndBatchLengths() (gas: 3967)\n[PASS] test_MetadataFreezesPermanently() (gas: 195226)\n[PASS] test_NoOwnerSeizureOrBurn() (gas: 418561)\n[PASS] test_OnlyTheFirstGrantIsImmediateEvenBeforeAnyMint() (gas: 546001)\n[PASS] test_OwnershipTwoStepAndRenounce() (gas: 244214)\n[PASS] test_RegrantingTheRevokedFirstMinterWaitsWithZeroSupply() (gas: 569038)\n[PASS] test_RejectedGrantDoesNotSpendTheBootstrap() (gas: 173991)\n[PASS] test_ReproposalRestartsDelayAndCancelDoesNotRevokeExistingRole() (gas: 457168)\n[PASS] test_RevokeIsImmediateClearsProposalsAndRegrantWaitsAgain() (gas: 535486)\n[PASS] test_RoyaltyDefaultAndLimits() (gas: 161390)\n[PASS] test_ZeroAddressesAndLegacyMinterSelectorCannotGrant() (gas: 340672)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 283.15ms (99.32ms CPU time)\n\nRan 23 tests for test/OGClubRaffle.t.sol:RaffleTest\n[PASS] testFuzz_ExactlyMinPrizesAndTicketsWinWithNoDuplicateTicket(uint8,uint8,bytes32) (runs: 256, μ: 1544577, ~: 1073192)\nLogs:\n  Bound result 9\n  Bound result 8\n\n[PASS] testFuzz_NoticeAlwaysMeasuredFromCreation(uint32) (runs: 256, μ: 241112, ~: 240936)\nLogs:\n  Bound result 2\n\n[PASS] test_ClaimToCannotRedirectAnotherWalletInTheSameBatch() (gas: 1239609)\n[PASS] test_ContractWalletCanRedirectButNobodyElseCan() (gas: 2015153)\n[PASS] test_DrawHeaderAndTargetExactBoundaries() (gas: 641712)\n[PASS] test_DuplicateWithinBatchRollsBackEverythingAndBitmapCrossesWords() (gas: 937264)\n[PASS] test_EntryFailureRollsBackRangesCapsAndPoints() (gas: 833603)\n[PASS] test_EntryWindowAndWalletCapExactBoundaries() (gas: 808341)\n[PASS] test_HugeTicketAndPrizeCountsDoNotRequireIterationToDrawOrClaim() (gas: 925425)\n[PASS] test_InvalidConfigurationPoolsLinesAndTickets() (gas: 941928)\n[PASS] test_Maximum32PoolsAnd128PrizeLines() (gas: 15557738)\n[PASS] test_MultiItemPoolMintsExactQuantitiesIncludingDuplicateAndZeroIds() (gas: 2370129)\n[PASS] test_NoticeExactBoundariesAndCancellation() (gas: 540021)\n[PASS] test_OwnerCannotModifyTermsPauseOrCancelStartedRaffle() (gas: 450829)\n[PASS] test_ReceiverCannotReenterEitherClaimPath() (gas: 1991045)\n[PASS] test_RejectingWalletDoesNotBlockOtherWinnersAndEmptyClaimRejected() (gas: 2030167)\n[PASS] test_RetargetOnlyAt257AndOldHeaderCannotDrawNewTarget() (gas: 560166)\n[PASS] test_RevokedMinterClaimIsRetryableAndDoesNotReroll() (gas: 1017518)\n[PASS] test_TicketPriceMultiplicationOverflowDoesNotSpendOrRecordEntry() (gas: 370843)\n[PASS] test_UnlimitedCapIsPerPoolAndRangesStayContiguous() (gas: 878602)\n[PASS] test_UnsoldPrizesAreRandomPositionsNotAlwaysTheTail() (gas: 3336643)\n[PASS] test_WrongKEntryAndDoubleClaimsRevertAtomically() (gas: 1332250)\n[PASS] test_WrongNumberInAuthenticatedHeaderRejected() (gas: 365306)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 283.19ms (331.83ms CPU time)\n\nRan 1 test for test/VaultInvariant.t.sol:VaultInvariantTest\n[PASS] invariant_VaultAlwaysCoversReservationsAndOnlyClaimsMoveTokens() (runs: 128, calls: 8192, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | advance  | 1307  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | cancel   | 1354  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | claim    | 1366  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1377  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | propose  | 1436  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | release  | 1352  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 1000000000000000000000\n  Bound result 100000000000000000000\n  Bound result 604800\n  Bound result 100000000000000000000\n  Bound result 259200\n  Bound result 345600\n  Bound result 100000000000000000000\n  Bound result 8035200\n  Bound result 3063565111\n  Bound result 855\n  Bound result 4716\n  Bound result 210607787\n  Bound result 240\n  Bound result 20525562795\n  Bound result 12125\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 7798\n  Bound result 5984\n  Bound result 2947\n  Bound result 3689274\n  Bound result 7628737\n  Bound result 400\n  Bound result 192\n  Bound result 2930\n  Bound result 1001\n  Bound result 107477462\n  Bound result 11055\n  Bound result 42\n  Bound result 2879792\n  Bound result 555\n  Bound result 717\n  Bound result 2248\n  Bound result 2755\n  Bound result 7\n  Bound result 6720\n  Bound result 1415071841494791321\n  Bound result 123456\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.48s (2.48s CPU time)\n\nRan 1 test for test/StakingInvariant.t.sol:StakingInvariantTest\n[PASS]\nStakingInvariantTest invariants:\n[PASS] invariant_PointsAppearOnlyByTimeWeightedAccrualAndLeaveOnlyBySpending\n[PASS] invariant_StakingBalanceEqualsAllStakes\n StakingInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| StakingHandler | advance           | 1684  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | spend             | 1645  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | stake             | 1650  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unauthorizedSpend | 1582  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unstake           | 1631  | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10000000000000000000\n  Bound result 86400\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 2264337593543950335\n  Bound result 6305\n  Bound result 0\n  Bound result 2998\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 1296743294243\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 2947\n  Bound result 128\n  Bound result 0\n  Bound result 0\n  Bound result 245\n  Bound result 183\n  Bound result 10\n  Bound result 969\n  Bound result 245\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 0\n  Bound result 36\n  Bound result 854742525\n  Bound result 490\n  Bound result 1\n  Bound result 21\n  Bound result 1343494888\n  Bound result 3\n  Bound result 514264337593543950335\n  Bound result 771998\n  Bound result 149689680\n  Bound result 257\n  Bound result 48118400013066680270\n  Bound result 101\n  Bound result 514264337593543950335\n  Bound result 9\n  Bound result 11\n  Bound result 0\n  Bound result 5582\n  Bound result 0\n  Bound result 101\n  Bound result 1079\n  Bound result 514264337593543950335\n  Bound result 215\n  Bound result 771998\n  Bound result 1296743297242\n  Bound result 2347\n  Bound result 3180\n  Bound result 731\n  Bound result 0\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.34s (3.34s CPU time)\n\nRan 1 test for test/StakingInvariant.t.sol:FeeStakingInvariantTest\n[PASS]\nFeeStakingInvariantTest invariants:\n[PASS] invariant_PointsAppearOnlyByTimeWeightedAccrualAndLeaveOnlyBySpending\n[PASS] invariant_StakingBalanceEqualsAllStakes\n FeeStakingInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| StakingHandler | advance           | 1684  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | spend             | 1645  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | stake             | 1650  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unauthorizedSpend | 1582  | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| StakingHandler | unstake           | 1631  | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10000000000000000000\n  Bound result 86400\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 6264337593543950335\n  Bound result 6277\n  Bound result 2240\n  Bound result 0\n  Bound result 65279\n  Bound result 514264337593543950335\n  Bound result 1001\n  Bound result 1296743294243\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 3068\n  Bound result 128\n  Bound result 0\n  Bound result 0\n  Bound result 1384\n  Bound result 183\n  Bound result 10\n  Bound result 892\n  Bound result 1001\n  Bound result 0\n  Bound result 514264337593543950335\n  Bound result 1\n  Bound result 319379\n  Bound result 4383992273226118098911\n  Bound result 1001\n  Bound result 1001\n  Bound result 597929524923\n  Bound result 4032\n  Bound result 3\n  Bound result 88\n  Bound result 95\n  Bound result 514264337593543950335\n  Bound result 771998\n  Bound result 149689680\n  Bound result 257\n  Bound result 2792\n  Bound result 10000\n  Bound result 514264337593543950335\n  Bound result 2468\n  Bound result 9\n  Bound result 11\n  Bound result 1001\n  Bound result 7199\n  Bound result 1570148199\n  Bound result 101\n  Bound result 1189\n  Bound result 514264337593543950335\n  Bound result 215\n  Bound result 771998\n  Bound result 8840915515454\n  Bound result 2851\n  Bound result 4976\n  Bound result 96\n  Bound result 4988\n  Bound result 11575608077352841579106\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.41s (3.41s CPU time)\n\nRan 1 test for test/FurnitureInvariant.t.sol:FurnitureInvariantTest\n[PASS]\nFurnitureInvariantTest invariants:\n[PASS] invariant_BalancesAndSupplyMatchGhosts\n[PASS] invariant_FrozenMetadataNeverChangesAndRoyaltyIsBounded\n[PASS] invariant_OwnerNeverHoldsOrDestroysAnything\n FurnitureInvariantTest invariants (runs: 96, calls: 7680, reverts: 0)\n\n╭------------------+--------------------------+-------+---------+----------╮\n| Contract         | Selector                 | Calls | Reverts | Discards |\n+==========================================================================+\n| FurnitureHandler | mint                     | 1165  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | operatorBatchTransfer    | 1068  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | ownerMetadata            | 1112  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | ownerTriesToSeize        | 1061  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | revokeApproval           | 1112  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | strangerCannotAdminister | 1075  | 0       | 0        |\n|------------------+--------------------------+-------+---------+----------|\n| FurnitureHandler | transfer                 | 1087  | 0       | 0        |\n╰------------------+--------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 5\n  Bound result 14\n  Bound result 1\n  Bound result 14\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 5\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 13\n  Bound result 14\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 9\n  Bound result 0\n  Bound result 10\n  Bound result 7\n  Bound result 8\n  Bound result 3\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 8\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 6\n  Bound result 5\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 4\n  Bound result 9\n  Bound result 0\n  Bound result 4\n  Bound result 14\n  Bound result 16\n  Bound result 14\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 4\n  Bound result 0\n  Bound result 6\n  Bound result 1008\n  Bound result 3\n  Bound result 0\n  Bound result 7\n  Bound result 0\n  Bound result 2\n  Bound result 11\n  Bound result 1\n  Bound result 0\n  Bound result 9\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 9\n  Bound result 6\n  Bound result 20\n  Bound result 14\n  Bound result 13\n  Bound result 14\n  Bound result 3\n  Bound result 4\n  Bound result 2\n  Bound result 7\n  Bound result 15\n  Bound result 10\n  Bound result 882\n  Bound result 5\n  Bound result 2\n  Bound result 12\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 10\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 9\n  Bound result 12\n  Bound result 7\n  Bound result 24\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 8\n  Bound result 0\n  Bound result 2\n  Bound result 7\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 599\n  Bound result 14\n  Bound result 0\n  Bound result 1\n  Bound result 9\n  Bound result 3\n  Bound result 0\n  Bound result 5\n  Bound result 0\n  Bound result 2\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 8.91s (8.90s CPU time)\n\nRan 13 test suites in 8.91s (19.79s CPU time): 104 tests passed, 0 failed, 0 skipped (104 total tests)\n","passed":true},{"durationMs":118,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OGClubFarmVault.acceptOwnership()\",\"OGClubFarmVault.cancelSeason(uint256)\",\"OGClubFarmVault.claim(uint256,address,uint256,bytes32[])\",\"OGClubFarmVault.proposeSeason(bytes32,uint256)\",\"OGClubFarmVault.releaseSeason(uint256)\",\"OGClubFarmVault.renounceOwnership()\",\"OGClubFarmVault.transferOwnership(address)\",\"OGClubFurniture.acceptOwnership()\",\"OGClubFurniture.activateMinter(address)\",\"OGClubFurniture.cancelMinter(address)\",\"OGClubFurniture.freezeMetadata()\",\"OGClubFurniture.grantMinter(address)\",\"OGClubFurniture.mintBatch(address,uint256[],uint256[])\",\"OGClubFurniture.renounceOwnership()\",\"OGClubFurniture.revokeMinter(address)\",\"OGClubFurniture.safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\",\"OGClubFurniture.safeTransferFrom(address,address,uint256,uint256,bytes)\",\"OGClubFurniture.setApprovalForAll(address,bool)\",\"OGClubFurniture.setBaseURI(string)\",\"OGClubFurniture.setRoyalty(address,uint96)\",\"OGClubFurniture.transferOwnership(address)\",\"OGClubRaffle.acceptOwnership()\",\"OGClubRaffle.cancelRaffle(uint256)\",\"OGClubRaffle.claim(uint256,uint256,(uint256,uint256)[])\",\"OGClubRaffle.claimTo(uint256,uint256,(uint256,uint256)[],address)\",\"OGClubRaffle.commitDraw(uint256)\",\"OGClubRaffle.createRaffle(uint256,uint256,(uint8,uint256,uint256,(uint256,uint256)[])[])\",\"OGClubRaffle.draw(uint256,bytes)\",\"OGClubRaffle.enter(uint256,uint256,uint256)\",\"OGClubRaffle.renounceOwnership()\",\"OGClubRaffle.transferOwnership(address)\",\"OGClubStaking.acceptOwnership()\",\"OGClubStaking.activateSpender(address)\",\"OGClubStaking.cancelSpender(address)\",\"OGClubStaking.grantSpender(address)\",\"OGClubStaking.renounceOwnership()\",\"OGClubStaking.revokeSpender(address)\",\"OGClubStaking.spendPoints(address,uint256)\",\"OGClubStaking.stake(uint256)\",\"OGClubStaking.transferOwnership(address)\",\"OGClubStaking.unstake(uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":126,\"README.md\":290,\"VENDOR.md\":13,\"foundry.toml\":22,\"launch.json\":44,\"script/Deploy.s.sol\":59,\"script/encode_header.py\":82,\"src/OGClubFarmVault.sol\":115,\"src/OGClubFurniture.sol\":138,\"src/OGClubRaffle.sol\":357,\"src/OGClubStaking.sol\":176,\"src/libraries/BlockHeader.sol\":70,\"src/libraries/Permutation.sol\":30,\"src/mocks/MockOG.sol\":21,\"test/BlockHeader.t.sol\":144,\"test/Deployment.t.sol\":117,\"test/FurnitureInvariant.t.sol\":248,\"test/Gas.t.sol\":138,\"test/OGClubFarmVault.t.sol\":309,\"test/OGClubFurniture.t.sol\":362,\"test/OGClubRaffle.t.sol\":537,\"test/OGClubStaking.t.sol\":280,\"test/Permutation.t.sol\":49,\"test/RoleLifecycle.t.sol\":146,\"test/StakingInvariant.t.sol\":153,\"test/VaultInvariant.t.sol\":156,\"test/fixtures/MainnetHeaders.sol\":32,\"test/fixtures/SOURCES.md\":74,\"test/fixtures/SepoliaHeader.sol\":14,\"test/fixtures/mainnet-cancun.json\":24,\"test/fixtures/mainnet-prague.json\":25,\"test/fixtures/mainnet-shanghai.json\":21,\"test/fixtures/sepolia-11921684.json\":27,\"test/helpers/HeaderBuilder.sol\":48,\"test/helpers/RaffleTestBase.sol\":98,\"test/helpers/TokenMocks.sol\":93,\"test/test_encode_header.py\":65,\"test/test_launch.py\":47},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":5411,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/OGClubStaking.sol:164: OGClubStaking._pending(OGClubStaking.Account) (src/OGClubStaking.sol#164-175) uses a weak PRNG: \"remainder = uint80(fraction % denominator) (src/OGClubStaking.sol#174)\"\n[high/medium] reentrancy-balance at src/OGClubFarmVault.sol:78: Reentrancy in OGClubFarmVault.claim(uint256,address,uint256,bytes32[]) (src/OGClubFarmVault.sol#78-94):\n[high/medium] reentrancy-balance at src/OGClubStaking.sol:69: Reentrancy in OGClubStaking.stake(uint256) (src/OGClubStaking.sol#69-85):\n[high/medium] reentrancy-balance at src/OGClubStaking.sol:87: Reentrancy in OGClubStaking.unstake(uint256) (src/OGClubStaking.sol#87-100):\n[high/medium] reentrancy-balance at src/OGClubStaking.sol:87: Reentrancy in OGClubStaking.unstake(uint256) (src/OGClubStaking.sol#87-100):\n[medium/high] incorrect-equality at src/OGClubStaking.sol:69: OGClubStaking.stake(uint256) (src/OGClubStaking.sol#69-85) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/OGClubStaking.sol:164: OGClubStaking._pending(OGClubStaking.Account) (src/OGClubStaking.sol#164-175) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/OGClubStaking.sol:135: OGClubStaking.activateSpender(address) (src/OGClubStaking.sol#135-142) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/OGClubFurniture.sol:68: OGClubFurniture.activateMinter(address) (src/OGClubFurniture.sol#68-75) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/OGClubRaffle.sol:300: Reentrancy in OGClubRaffle._claim(uint256,uint256,OGClubRaffle.Win[],address) (src/OGClubRaffle.sol#300-325):\n[medium/medium] reentrancy-no-eth at src/OGClubStaking.sol:69: Reentrancy in OGClubStaking.stake(uint256) (src/OGClubStaking.sol#69-85):\n[medium/medium] uninitialized-local at src/OGClubRaffle.sol:163: OGClubRaffle.createRaffle(uint256,uint256,OGClubRaffle.PoolInput[]).prizeCount (src/OGClubRaffle.sol#163) is a local variable never initialized\n[medium/medium] uninitialized-local at src/libraries/Permutation.sol:13: Permutation.permute(uint256,uint256,bytes32).halfBits (src/libraries/Permutation.sol#13) is a local variable never initialized\n[medium/medium] uninitialized-local at src/OGClubRaffle.sol:148: OGClubRaffle.createRaffle(uint256,uint256,OGClubRaffle.PoolInput[]).lines (src/OGClubRaffle.sol#148) is a local variable never initialized\n[medium/medium] uninitialized-local at src/OGClubRaffle.sol:241: OGClubRaffle.prizeOf(uint256,uint256,uint256).low (src/OGClubRaffle.sol#241) is a local variable never initialized\n[low/medium] calls-loop at src/OGClubRaffle.sol:300: OGClubRaffle._claim(uint256,uint256,OGClubRaffle.Win[],address) (src/OGClubRaffle.sol#300-325) has external calls inside a loop: furniture.mintBatch(to,ids,amounts) (src/OGClubRaffle.sol#322)\n[low/medium] calls-loop at src/OGClubRaffle.sol:300: OGClubRaffle._claim(uint256,uint256,OGClubRaffle.Win[],address) (src/OGClubRaffle.sol#300-325) has external calls inside a loop: furniture.mintBatch(to,ids,amounts) (src/OGClubRaffle.sol#322)\n[low/medium] reentrancy-benign at src/OGClubStaking.sol:69: Reentrancy in OGClubStaking.stake(uint256) (src/OGClubStaking.sol#69-85):\n[low/medium] timestamp at src/OGClubStaking.sol:144: OGClubStaking.cancelSpender(address) (src/OGClubStaking.sol#144-149) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubStaking.sol:112: OGClubStaking.spendPoints(address,uint256) (src/OGClubStaking.sol#112-118) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubFurniture.sol:78: OGClubFurniture.cancelMinter(address) (src/OGClubFurniture.sol#78-83) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubFarmVault.sol:56: OGClubFarmVault.proposeSeason(bytes32,uint256) (src/OGClubFarmVault.sol#56-66) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubFarmVault.sol:96: OGClubFarmVault.releaseSeason(uint256) (src/OGClubFarmVault.sol#96-102) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubRaffle.sol:176: OGClubRaffle.cancelRaffle(uint256) (src/OGClubRaffle.sol#176-181) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubRaffle.sol:183: OGClubRaffle.enter(uint256,uint256,uint256) (src/OGClubRaffle.sol#183-199) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubFarmVault.sol:68: OGClubFarmVault.cancelSeason(uint256) (src/OGClubFarmVault.sol#68-74) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubRaffle.sol:138: OGClubRaffle.createRaffle(uint256,uint256,OGClubRaffle.PoolInput[]) (src/OGClubRaffle.sol#138-174) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubFarmVault.sol:78: OGClubFarmVault.claim(uint256,address,uint256,bytes32[]) (src/OGClubFarmVault.sol#78-94) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubStaking.sol:135: OGClubStaking.activateSpender(address) (src/OGClubStaking.sol#135-142) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubFurniture.sol:68: OGClubFurniture.activateMinter(address) (src/OGClubFurniture.sol#68-75) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubStaking.sol:164: OGClubStaking._pending(OGClubStaking.Account) (src/OGClubStaking.sol#164-175) uses timestamp for comparisons\n[low/medium] timestamp at src/OGClubRaffle.sol:203: OGClubRaffle.commitDraw(uint256) (src/OGClubRaffle.sol#203-211) uses timestamp for comparisons","passed":true},{"durationMs":1144,"exitCode":0,"name":"aderyn","output":"[high] eth-send-unchecked-address at src/OGClubStaking.sol:69: ETH transferred without address checks (2 places)\n[high] reentrancy-state-change at src/OGClubFarmVault.sol:59: Reentrancy: State change after external call (4 places)\n[high] storage-array-memory-edit at src/OGClubStaking.sol:103: Storage Array Edited with Memory\n[high] unsafe-casting at src/OGClubRaffle.sol:193: Unsafe Casting of integers (2 places)\n[low] centralization-risk at src/OGClubFarmVault.sol:12: Centralization Risk (18 places)\n[low] costly-loop at src/OGClubRaffle.sol:149: Costly operations inside loop (4 places)\n[low] large-numeric-literal at src/OGClubStaking.sol:94: Large Numeric Literal (2 places)\n[low] literal-instead-of-constant at src/OGClubFurniture.sol:46: Literal Instead of Constant (17 places)\n[low] non-reentrant-not-first at src/OGClubFarmVault.sol:56: `nonReentrant` is Not the First Modifier (3 places)\n[low] push-zero-opcode at src/OGClubFarmVault.sol:2: PUSH0 Opcode (7 places)\n[low] require-revert-in-loop at src/OGClubRaffle.sol:149: Loop Contains `require`/`revert` (5 places)\n[low] uninitialized-local-variable at src/OGClubRaffle.sol:149: Uninitialized Local Variable (6 places)\n[low] unspecific-solidity-pragma at src/OGClubFarmVault.sol:2: Unspecific Solidity Pragma (5 places)\n[low] unused-public-function at src/OGClubRaffle.sol:262: Public Function Not Used Internally (2 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"f8a0e15e3266fc53e2704ae3aa08fe2b871eed72f941065bee9434c42e538b7a","verifiedTreeHash":"fdb543b279e99374d474257888e23d3dcd53d3f9","verifierVersion":"0.1.0+745c1db4"}]}