@ballkidz/defifa 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ADMINISTRATION.md CHANGED
@@ -1,166 +1,79 @@
1
1
  # Administration
2
2
 
3
- Admin privileges and their scope in defifa-collection-deployer-v6.
4
-
5
3
  ## At A Glance
6
4
 
7
5
  | Item | Details |
8
- |------|---------|
9
- | Scope | Defifa game launch, scorecard ratification, lifecycle progression, and fee-project ownership locking. |
10
- | Operators | Permissionless game creators and scorecard participants, plus the protocol contracts `DefifaDeployer`, `DefifaGovernor`, `DefifaHook`, and optional `DefifaProjectOwner`. |
11
- | Highest-risk actions | Launching a game with bad immutable parameters, ratifying the winning scorecard, or transferring a fee-project NFT into `DefifaProjectOwner`. |
12
- | Recovery posture | Game parameters are intentionally immutable after launch. A bad game setup usually means launching a new game or falling back to the no-contest path if available. |
13
-
14
- ## Routine Operations
6
+ | --- | --- |
7
+ | Scope | Game launch configuration, scorecard governance, no-contest recovery, and optional fee-project ownership locking |
8
+ | Control posture | Permissionless launch, then collective governance plus bounded contract-controlled lifecycle paths |
9
+ | Highest-risk actions | Launching with wrong immutable game settings, misconfiguring governance thresholds, and misunderstanding no-contest handling |
10
+ | Recovery posture | Mostly replacement or documented no-contest handling; there is no broad post-launch owner override |
15
11
 
16
- - Validate game timings, tier setup, fee routing, and attestation settings before calling `launchGameWith()`.
17
- - During scoring, rely on the documented submission, attestation, and ratification flow rather than looking for discretionary admin overrides that do not exist.
18
- - Use `triggerNoContestFor()` when the game has entered the documented no-contest condition and refunds need to be unlocked.
19
- - Treat the fee-project ownership proxy as a burn-lock mechanism, not a recoverable custody tool.
12
+ ## Purpose
20
13
 
21
- ## One-Way Or High-Risk Actions
22
-
23
- - `launchGameWith()` fixes the game's core configuration.
24
- - `setTierCashOutWeightsTo()` is irreversible once weights are set for a game.
25
- - `DefifaProjectOwner` permanently locks the project NFT it receives.
14
+ `defifa` is unusual because game creation is permissionless but ongoing game control is intentionally narrow. The main administration job is understanding what is fixed at launch, what collective governance can still do, and what the deployer must do to finish settlement.
26
15
 
27
- ## Recovery Notes
16
+ ## Control Model
28
17
 
29
- - If a scorecard never reaches a valid ratification path and timeout conditions are met, use the documented no-contest recovery flow.
30
- - If the game launched with the wrong immutable economics or timing, recovery is a replacement game deployment rather than an admin patch.
18
+ - `launchGameWith(...)` is the real governance commitment. Core game shape is fixed there.
19
+ - `DefifaGovernor` controls scorecard submission, attestation, and ratification.
20
+ - `DefifaHook` controls phase-aware mint and cash-out behavior but does not expose broad admin mutability.
21
+ - `DefifaDeployer` still owns structural lifecycle duties such as fulfillment and no-contest queuing.
22
+ - `DefifaProjectOwner` is an optional irreversible sink for the fee-project NFT.
31
23
 
32
24
  ## Roles
33
25
 
34
- | Role | Who | How Assigned |
35
- |------|-----|-------------|
36
- | **Game Creator** | Any EOA or contract that calls `DefifaDeployer.launchGameWith()` | Self-selected; permissionless |
37
- | **DefifaDeployer** (contract) | Singleton deployed at protocol setup | Immutable; owns all game JB projects and the governor |
38
- | **DefifaGovernor** (contract) | Singleton; `Ownable` by the DefifaDeployer | Ownership transferred from deployer at construction |
39
- | **DefifaHook** (per-game clone) | One clone per game; `Ownable` by the DefifaGovernor | Ownership transferred from deployer during `launchGameWith()` |
40
- | **DefifaProjectOwner** | Optional proxy contract that holds the Defifa fee project NFT | Receives project NFT; grants `SET_SPLIT_GROUPS` to deployer |
41
- | **Scorecard Submitter** | Any address during SCORING phase | Permissionless (`submitScorecardFor`) |
42
- | **Attestor** | Any NFT holder with attestation weight | Must hold game NFTs; weight proportional to holdings per tier |
43
- | **Default Attestation Delegate** | Address set at game launch | Set via `DefifaLaunchProjectData.defaultAttestationDelegate` |
44
- | **Tier Delegate** | Any address delegated attestation units by an NFT holder | Set via `setTierDelegateTo` / `setTierDelegatesTo` during MINT phase only |
45
-
46
- ## Privileged Functions
47
-
48
- ### DefifaDeployer
49
-
50
- | Function | Required Role | Permission Check | What It Does |
51
- |----------|--------------|-----------------|-------------|
52
- | `launchGameWith()` | Anyone | None (permissionless) | Creates a new JB project, clones DefifaHook, initializes governor, configures rulesets with MINT/REFUND/SCORING phases. Game parameters are immutable after this call. |
53
- | `fulfillCommitmentsOf()` | Anyone | Guarded by `fulfilledCommitmentsOf[gameId] != 0` reentrancy check; requires `cashOutWeightIsSet` on the hook | Sends fee payouts (Defifa 5% + NANA 2.5% + user splits) via try-catch `sendPayoutsOf`, then queues the final COMPLETE ruleset. If payout fails, emits `CommitmentPayoutFailed` and sets sentinel. Can only execute once per game. |
54
- | `triggerNoContestFor()` | Anyone | Requires `currentGamePhaseOf(gameId) == NO_CONTEST` and `!noContestTriggeredFor[gameId]` | Queues a new ruleset without payout limits so surplus equals balance, enabling full refunds. Can only execute once per game. |
55
-
56
- ### DefifaGovernor
57
-
58
- | Function | Required Role | Permission Check | What It Does |
59
- |----------|--------------|-----------------|-------------|
60
- | `initializeGame()` | DefifaDeployer (owner) | `onlyOwner` | Sets the attestation start time, attestation grace period, and optional post-quorum `timelockDuration` for a game. Enforces a minimum 1-day grace period. Called automatically during `launchGameWith()`. |
61
- | `submitScorecardFor()` | Anyone | Must be in SCORING phase; no ratified scorecard yet; no duplicate scorecard hash; weighted tiers must have nonzero supply | Submits a scorecard for attestation. Sets `attestationsBegin` and `gracePeriodEnds` timestamps. Snapshots pending reserves per tier for BWA computation. |
62
- | `attestToScorecardFrom()` | Any NFT holder | Must be in SCORING phase; scorecard must be `ACTIVE`, `QUEUED`, or `SUCCEEDED`; caller cannot have already attested | Records attestation weight based on tier holdings at the `attestationsBegin - 1` checkpoint timestamp. Uses pending reserve snapshot from submission time. |
63
- | `ratifyScorecardFrom()` | Anyone | Scorecard must be in SUCCEEDED state (quorum met, grace period elapsed, and any configured `timelockDuration` elapsed); no scorecard already ratified | Executes the scorecard via low-level call to `setTierCashOutWeightsTo` on the hook, then calls `fulfillCommitmentsOf`. |
64
-
65
- ### DefifaHook
66
-
67
- | Function | Required Role | Permission Check | What It Does |
68
- |----------|--------------|-----------------|-------------|
69
- | `initialize()` | DefifaDeployer | Reverts if `address(this) == codeOrigin` or already initialized (`store != address(0)`) | One-time initialization of the cloned hook with game configuration, tiers, and tier names. Transfers ownership to caller. |
70
- | `setTierCashOutWeightsTo()` | DefifaGovernor (owner) | `onlyOwner`; must be in SCORING phase; weights not already set | Sets the cash-out weight distribution across tiers. Validates weights sum to `TOTAL_CASHOUT_WEIGHT` (1e18). Irreversible -- once set, `cashOutWeightIsSet` is permanently true. |
71
- | `setTierDelegateTo()` | Any NFT holder | Must be in MINT phase | Delegates attestation units for a specific tier to another address. |
72
- | `setTierDelegatesTo()` | Any NFT holder | Must be in MINT phase; delegatee cannot be address(0) | Batch delegation of attestation units across multiple tiers. |
73
- | `mintReservesFor()` | Anyone | Reverts if `pauseMintPendingReserves` is set in ruleset metadata | Mints reserved tokens to the tier's reserve beneficiary. Increments `_totalMintCost` so reserved recipients can claim fee tokens. |
74
- | `afterPayRecordedWith()` | JB Terminal | Caller must be a terminal of the project; `msg.value` must be 0 | Processes payment: validates currency, mints NFTs, sets up attestation delegation. |
75
- | `afterCashOutRecordedWith()` | JB Terminal | Caller must be a terminal of the project; `msg.value` must be 0 | Burns NFTs on cash-out, tracks redeemed amounts, distributes fee tokens during COMPLETE phase. |
76
- | `transferOwnership()` | Current owner | `onlyOwner` (inherited from Ownable) | Transfers hook ownership. Used once during deployment to transfer from deployer to governor. |
77
-
78
- ### DefifaProjectOwner
79
-
80
- | Function | Required Role | Permission Check | What It Does |
81
- |----------|--------------|-----------------|-------------|
82
- | `onERC721Received()` | JBProjects contract | `msg.sender` must be the JBProjects contract | When the Defifa fee project NFT is transferred here, auto-grants `SET_SPLIT_GROUPS` permission to the DefifaDeployer. The project NFT is permanently locked -- cannot be recovered. |
83
-
84
- ## Game Lifecycle Administration
85
-
86
- The game lifecycle is fully automated through Juicebox rulesets configured at launch. No admin can change phases manually.
87
-
88
- ```
89
- COUNTDOWN --> MINT --> REFUND (optional) --> SCORING --> COMPLETE or NO_CONTEST
90
- ```
91
-
92
- **Phase transitions are time-based, encoded in JBRuleset durations:**
93
- - **COUNTDOWN**: Before `start - mintPeriodDuration - refundPeriodDuration`. Cycle number 0.
94
- - **MINT**: Duration = `mintPeriodDuration`. Payments open, refunds at mint price. Cycle number 1.
95
- - **REFUND**: Duration = `refundPeriodDuration` (optional, only if nonzero). Payments paused, refunds still at mint price. Cycle number 2.
96
- - **SCORING**: Duration = 0 (no expiry). Payments paused. Cash-out weights must be set via governance. Cycle number 3+.
97
- - **COMPLETE**: Entered when `cashOutWeightIsSet == true`. Cash-outs use scorecard weights.
98
- - **NO_CONTEST**: Entered when `minParticipation` threshold is not met, or `scorecardTimeout` elapses without ratification. Requires `triggerNoContestFor()` to unlock refunds.
99
-
100
- **Who controls scoring:**
101
- 1. Anyone submits a scorecard during SCORING (`submitScorecardFor`)
102
- 2. NFT holders attest based on their per-tier voting weight (`attestToScorecardFrom`)
103
- 3. Once quorum (50% of minted tiers' attestation power) is met, the grace period has elapsed, and any configured `timelockDuration` has elapsed, the scorecard reaches `SUCCEEDED` and anyone can ratify it with `ratifyScorecardFrom`
104
- 4. The governor calls `setTierCashOutWeightsTo` on the hook via low-level call
105
- 5. `fulfillCommitmentsOf` sends fee payouts (try-catch) and queues the final ruleset
106
-
107
- ### Attestation Quorum Details
108
-
109
- The quorum threshold is 50% of the total attestation power across all tiers with nonzero mint supply. Attestation power per tier is proportional to the tier's minted supply at the `attestationsBegin - 1` checkpoint timestamp, with pending reserves snapshotted at scorecard submission time to prevent reserve minting from inflating attestation power.
110
-
111
- **Edge cases:**
112
- - **Tiers with zero mints:** Tiers with `currentSupplyOfTier(tierId) == 0` are excluded from the quorum calculation. They have no attestation power and cannot influence scoring.
113
- - **All mints in a single tier:** If all participation concentrates in one tier, that tier's holders control the quorum. The 50% threshold still applies -- holders of 50% of that tier's supply can ratify a scorecard.
114
- - **Grace period and timelock:** After submission, a scorecard stays `ACTIVE` until its grace period ends. If it has quorum at that point, it becomes `QUEUED` when `timelockDuration > 0`, or `SUCCEEDED` immediately when `timelockDuration == 0`. Attestations remain allowed while the scorecard is `ACTIVE`, `QUEUED`, or `SUCCEEDED`, but revocations are only allowed while it is `ACTIVE`. Ratification is only allowed from `SUCCEEDED`.
115
- - **Competing scorecards:** Multiple scorecards can be submitted. Each tracks attestations independently. Only the first to be ratified after meeting quorum, clearing the grace period, and clearing any configured timelock takes effect. Once ratified, no other scorecard can be ratified for the same game.
116
- - **Scorecard timeout:** If `scorecardTimeout` is nonzero and elapses without ratification, the game enters NO_CONTEST state, enabling full refunds via `triggerNoContestFor()`.
117
-
118
- **No single entity controls scoring.** The process requires collective attestation from NFT holders across tiers.
119
-
120
- ## Immutable Configuration
121
-
122
- The following are set at game creation and cannot be changed:
123
-
124
- | Parameter | Set In | Notes |
125
- |-----------|--------|-------|
126
- | Tier prices | `launchGameWith()` | Uniform price across all tiers (`tierPrice`) |
127
- | Tier count and names | `launchGameWith()` | Stored in hook during `initialize()` |
128
- | Game timing (start, mint duration, refund duration) | `launchGameWith()` | Encoded as JBRuleset durations |
129
- | Payment token | `launchGameWith()` | Single token per game |
130
- | Fee structure | Constructor constants | `DEFIFA_FEE_DIVISOR = 20` (5%), `BASE_PROTOCOL_FEE_DIVISOR = 40` (2.5%) |
131
- | Attestation start time | `launchGameWith()` | Stored in governor via `initializeGame()` |
132
- | Attestation grace period | `launchGameWith()` | Minimum 1 day enforced in `initializeGame()` |
133
- | Timelock duration | `launchGameWith()` | Optional cooling period after quorum before a scorecard becomes ratifiable |
134
- | Default attestation delegate | `launchGameWith()` | Stored in hook |
135
- | `minParticipation` threshold | `launchGameWith()` | 0 = disabled |
136
- | `scorecardTimeout` | `launchGameWith()` | 0 = disabled |
137
- | User splits | `launchGameWith()` | Stored as JB split groups at game creation |
138
- | Hook code origin | Constructor | Template contract for cloning |
139
- | `TOTAL_CASHOUT_WEIGHT` | Constant | 1e18, cannot be changed |
140
- | JB project ownership | `launchGameWith()` | Project owned by DefifaDeployer contract |
26
+ | Role | How Assigned | Scope | Notes |
27
+ | --- | --- | --- | --- |
28
+ | Game creator | Calls `launchGameWith(...)` | Launch only | Does not receive broad runtime admin power afterward |
29
+ | Scorecard participant | Holds or receives attestation power | Per game | Can submit, attest, revoke, and help ratify |
30
+ | Ratification path caller | Any caller who meets the documented conditions | Per game | Finalizes a valid scorecard |
31
+ | Fulfillment path caller | Any valid caller once ratified | Per game | Must run the completion commitment path |
32
+ | `DefifaProjectOwner` holder | Project NFT sent into sink | Per fee project | Irreversible ownership lock |
141
33
 
142
- ## Admin Boundaries
143
-
144
- What admins CANNOT do:
34
+ ## Privileged Surfaces
145
35
 
146
- 1. **No one can change game rules after launch.** Tier prices, timing, token, fees, and split configuration are all immutable.
36
+ - `launchGameWith(...)` fixes phase timing, tiers, fee routing, and governance shape
37
+ - `submitScorecardFor(...)`, `attestToScorecardFrom(...)`, `revokeAttestationFrom(...)`, and `ratifyScorecardFrom(...)` govern outcome selection
38
+ - `fulfillCommitmentsOf(...)` turns a ratified scorecard into real settlement
39
+ - `triggerNoContestFor(...)` moves failed games into the documented recovery path
147
40
 
148
- 2. **No one can unilaterally set scorecard weights.** The `setTierCashOutWeightsTo` function requires `onlyOwner` (the governor), and the governor only calls it after a scorecard reaches quorum through collective attestation.
41
+ ## Immutable And One-Way
149
42
 
150
- 3. **No one can pause or cancel a game.** Once launched, the game proceeds through its phases automatically based on time.
43
+ - Game phase timing is fixed at launch.
44
+ - Scorecard timeout, minimum participation, and default delegation choices are fixed at launch.
45
+ - `setTierCashOutWeightsTo()` is effectively one-way once final weights are installed.
46
+ - `cashOutWeightIsSet` permanently closes the score-setting path after success.
47
+ - `DefifaProjectOwner` permanently locks the project NFT it receives.
48
+ - `fulfillCommitmentsOf()` and `triggerNoContestFor()` are single-use style lifecycle paths.
151
49
 
152
- 4. **No one can extract funds from the treasury.** The `ownerMustSendPayouts` flag is set on the SCORING ruleset, and payouts are limited to the pre-configured splits. The deployer can only send payouts matching the split configuration.
50
+ ## Operational Notes
153
51
 
154
- 5. **No one can mint new tiers or change tier supply.** Tiers are set once during `initialize()` with `cannotBeRemoved: true`.
52
+ - Validate game timings, tier setup, fee routing, and attestation settings before launch.
53
+ - Treat `launchGameWith()` as the real admin commitment.
54
+ - During scoring, follow the submission, attestation, and ratification flow rather than looking for discretionary overrides.
55
+ - Use `triggerNoContestFor()` only when the game has actually entered the documented no-contest condition.
56
+ - Treat the fee-project ownership proxy as a burn-lock mechanism, not a recoverable custody tool.
155
57
 
156
- 6. **No one can change delegates after MINT phase.** `setTierDelegateTo` and `setTierDelegatesTo` both revert with `DefifaHook_DelegateChangesUnavailableInThisPhase` outside MINT.
58
+ ## Machine Notes
157
59
 
158
- 7. **No one can re-set cash-out weights.** The `cashOutWeightIsSet` flag is checked before setting and the function reverts with `DefifaHook_CashoutWeightsAlreadySet`.
60
+ - Do not infer ongoing admin power for the game creator; launch is permissionless but not an ongoing authority grant.
61
+ - Treat `DefifaDeployer`, `DefifaGovernor`, `DefifaHook`, and `DefifaProjectOwner` as the minimum source-of-truth set for authority review.
62
+ - If scorecard state, quorum assumptions, or timeout state differ from the expected lifecycle, inspect the current phase before documenting the next action.
63
+ - If a game launched with wrong immutable economics, timing, or split assumptions, do not guess at an in-place fix.
159
64
 
160
- 8. **No one can re-ratify a scorecard.** The `ratifiedScorecardIdOf[gameId] != 0` check prevents double ratification.
65
+ ## Recovery
161
66
 
162
- 9. **No one can fulfill commitments twice.** The `fulfilledCommitmentsOf[gameId] != 0` check prevents re-entry.
67
+ - If a scorecard never reaches a valid ratification path and timeout conditions are met, use the documented no-contest flow.
68
+ - If a game launched with wrong immutable economics, timing, fee routing, or tier design, recovery is usually a replacement deployment.
69
+ - If fee-project ownership was transferred into `DefifaProjectOwner`, there is no recovery path for that NFT.
70
+ - There is no broad owner override that can pause, cancel, or rewrite a live game after launch.
163
71
 
164
- 10. **No one can recover the project NFT from DefifaProjectOwner.** Once transferred, the NFT is permanently locked.
72
+ ## Admin Boundaries
165
73
 
166
- 11. **The game creator has no ongoing privileges.** After `launchGameWith()` returns, the caller has no special role. All game administration is handled by the protocol contracts and collective governance.
74
+ - No one can change tier prices, timing, payment token, fees, or split configuration after launch.
75
+ - No one can unilaterally set scorecard weights without the documented governance path.
76
+ - No one can manually pause, cancel, or rewind a game phase.
77
+ - No one can set cash-out weights twice.
78
+ - No one can fulfill commitments twice.
79
+ - No one can recover the project NFT from `DefifaProjectOwner`.
package/ARCHITECTURE.md CHANGED
@@ -2,66 +2,130 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- `defifa-collection-deployer-v6` builds prediction games on top of Juicebox and the 721 tiers hook. Each game is a project with phased rulesets, a hook that mints and cashes out game-piece NFTs, and a governor that ratifies scorecards which decide how the prize pool is distributed.
5
+ `defifa` builds phased prediction games on top of Juicebox and the 721 hook stack. A game is a Juicebox project with a custom NFT hook, a scorecard governor, and a deployer that launches the project and later fulfills the economic commitments that make completion real.
6
6
 
7
- ## Boundaries
7
+ ## System Overview
8
8
 
9
- - `DefifaHook` owns game-piece behavior, delegation, and cash-out math.
10
- - `DefifaGovernor` owns scorecard submission, attestation, quorum, and ratification.
11
- - `DefifaDeployer` owns game launch and post-ratification commitment fulfillment.
12
- - Generic tier storage and terminal accounting stay in `nana-721-hook-v6` and `nana-core-v6`.
9
+ `DefifaHook`, `DefifaGovernor`, and `DefifaDeployer` form one game-state machine even though they are deployed separately. The hook owns game-piece NFT behavior, attestation delegation, and phase-sensitive cash-out weighting. The governor owns scorecard submission, attestation, quorum, and ratification. The deployer owns game launch, phased ruleset setup, and commitment fulfillment after governance decides the outcome.
13
10
 
14
- ## Main Components
11
+ ## Core Invariants
15
12
 
16
- | Component | Responsibility |
17
- | --- | --- |
18
- | `DefifaDeployer` | Launches phased projects, clones hooks, initializes the governor, and fulfills commitments |
19
- | `DefifaHook` | ERC-721 game pieces, attestation delegation, custom cash-out weighting, and game-state aware behavior |
20
- | `DefifaGovernor` | Scorecard proposals, attestations, quorum checks, grace periods, and ratification |
21
- | `DefifaHookLib` | Shared validation and weight math extracted to keep the hook within size limits |
22
- | `DefifaTokenUriResolver` | Dynamic token metadata and SVG rendering |
23
- | `DefifaProjectOwner` | Lock helper for the fee project |
13
+ - The game is economically coherent only if deployer, governor, and hook agree on phase progression.
14
+ - Ratification is the only path that should install final cash-out weights for the complete phase.
15
+ - Attestation power should reflect tier semantics, not raw circulating supply.
16
+ - Refund, scoring, complete, and no-contest behavior must be mutually coherent.
17
+ - The deployer's post-ratification fulfillment path is mandatory economics, not optional housekeeping.
18
+ - Completion-phase cash outs must account for already redeemed tokens and pending reserve dilution correctly.
24
19
 
25
- ## Runtime Model
20
+ ## Modules
21
+
22
+ | Module | Responsibility | Notes |
23
+ | --- | --- | --- |
24
+ | `DefifaDeployer` | Launches games, sets phased rulesets, clones hooks, initializes governance, and fulfills commitments | Launch-time and completion-time runtime surface |
25
+ | `DefifaHook` | NFT minting, delegation, game-phase-aware cash-out behavior, and completion claims | Main game-facing runtime hook |
26
+ | `DefifaGovernor` | Scorecard submission, attestation weighting, quorum, grace periods, and ratification | Governance surface |
27
+ | `DefifaHookLib` | Shared validation and weight math extracted from the hook | Bytecode-management helper |
28
+ | `DefifaTokenUriResolver` | Dynamic token metadata and SVG rendering | Metadata layer |
29
+ | `DefifaProjectOwner` | Irreversible project-owner sink that preserves selected operator permissions | Governance-sensitive helper |
30
+
31
+ ## Trust Boundaries
32
+
33
+ - Canonical treasury accounting, project ownership, rulesets, terminals, and payout mechanics remain in `nana-core-v6`.
34
+ - Tier storage, reserve minting mechanics, and generic ERC-721 behavior come from `nana-721-hook-v6`.
35
+ - `DefifaGovernor` is trusted to ratify scorecards only through its quorum, grace-period, and timelock rules.
36
+ - `DefifaDeployer` is trusted to convert governance output into the final completion envelope.
37
+
38
+ ## Critical Flows
39
+
40
+ ### Launch Game
26
41
 
27
42
  ```text
28
43
  creator
29
- -> DefifaDeployer launches a project with staged rulesets
30
- players
31
- -> mint tiered NFTs during the mint window
32
- holders
33
- -> optionally refund during the refund window
34
- attesters
35
- -> submit and attest to scorecards during scoring
36
- governor
37
- -> ratifies the winning scorecard after quorum and grace-period checks
38
- holders
39
- -> cash out NFTs for their share of the prize pool during completion
44
+ -> deployer validates mint/refund/start timings
45
+ -> deployer predicts the game project ID and clones a game hook deterministically
46
+ -> deployer builds phased rulesets and optional fee splits
47
+ -> controller launches the project
48
+ -> governor is initialized for the game
49
+ -> hook ownership and project ownership are transferred into the intended long-term shape
50
+ ```
51
+
52
+ ### Mint During Open Play
53
+
54
+ ```text
55
+ player
56
+ -> pays the game project during the mint window
57
+ -> hook mints the selected game-piece NFT tier
58
+ -> delegation state and total mint-cost accounting are updated
59
+ -> reserved mints and pending reserves continue to affect later completion claims
40
60
  ```
41
61
 
42
- ## Critical Invariants
62
+ ### Scorecard Governance
63
+
64
+ ```text
65
+ attester or proposer
66
+ -> governor accepts a scorecard candidate
67
+ -> attestation power is computed from tier-relative holdings
68
+ -> quorum, grace period, and timelock gates are enforced
69
+ -> governor ratifies exactly one winning scorecard
70
+ ```
71
+
72
+ ### Fulfill Commitments And Complete
73
+
74
+ ```text
75
+ authorized completion path
76
+ -> deployer reads the ratified outcome
77
+ -> deployer fulfills the game's promised commitments and queues the final ruleset
78
+ -> hook installs final cash-out weights
79
+ -> holders burn pieces during complete phase to reclaim their weighted share of the pot
80
+ ```
81
+
82
+ ## Accounting Model
83
+
84
+ This repo does not replace `nana-core-v6` treasury accounting. Its critical economic state is:
43
85
 
44
- - Delegation and attestation power must stay aligned with tier semantics; a scorecard system that can be inflated by supply alone breaks the game.
45
- - Ratification is the only path that should install final cash-out weights.
46
- - Refund, scoring, complete, and no-contest phases must remain mutually coherent. If phase transitions drift, funds get stuck.
47
- - The deployer's commitment-fulfillment logic is part of game completion, not optional bookkeeping.
86
+ - phase timestamps and game ops data in the deployer
87
+ - scorecard and attestation state in the governor
88
+ - tier cash-out weights, redeemed-token tracking, mint-cost totals, and delegation state in the hook
48
89
 
49
- ## Where Complexity Lives
90
+ The hook's completion math is intentionally phase-sensitive:
50
91
 
51
- - The game is split across hook, governor, and deployer contracts, but users experience it as one state machine.
52
- - Scorecard weighting, attestation accounting, and phase transitions are tightly coupled.
53
- - Completion logic is economically sensitive because it combines prize distribution with fee fulfillment.
92
+ - before completion, cash-out behavior is refund or fallback oriented
93
+ - after ratification and fulfillment, cash-out weights become the game outcome
94
+ - completion claims use minted cost, redeemed tracking, and pending-reserve-aware dilution together
54
95
 
55
- ## Dependencies
96
+ ## Security Model
56
97
 
57
- - `nana-721-hook-v6` for tiered NFT infrastructure
58
- - `nana-core-v6` for phased rulesets, terminals, and payout mechanics
59
- - Juicebox governance and permission surfaces for project ownership and split updates
98
+ - The primary risk is semantic drift across hook, governor, and deployer.
99
+ - Ratification and fulfillment are separate steps; a ratified scorecard without correct fulfillment still leaves the game economically unfinished.
100
+ - Attestation weighting is part of game fairness, not just governance plumbing.
101
+ - Pending reserves and reserved-mint behavior affect both quorum fairness and completion-time claim dilution.
102
+ - Phase transitions are safety-critical. A timing bug can enable refunds, scoring, or completion in the wrong order.
60
103
 
61
104
  ## Safe Change Guide
62
105
 
63
- - Treat phase logic, governor logic, and hook cash-out logic as one system.
64
- - If you change scorecard validation, also inspect attestation weighting and ratification thresholds.
65
- - Keep `DefifaHookLib` and hook storage assumptions in sync; library extraction is for size, not for a separate trust boundary.
66
- - Do not move generic 721 behavior into Defifa just because the game uses it heavily.
67
- - When in doubt, trace an end-to-end game lifecycle rather than auditing one contract in isolation.
106
+ - Review `DefifaHook`, `DefifaGovernor`, and `DefifaDeployer` together for any nontrivial change.
107
+ - If phase semantics change, re-check mint, refund, scoring, ratification, fulfillment, and completion cash-out behavior together.
108
+ - If attestation math changes, inspect tier semantics, delegation, quorum, and ratification thresholds together.
109
+ - If completion claim math changes, re-check redeemed tracking, pending reserve dilution, and fee-token side claims in the same review.
110
+
111
+ ## Canonical Checks
112
+
113
+ - governor state transitions and scorecard handling:
114
+ `test/DefifaGovernor.t.sol`
115
+ - fulfillment and ratification coupling:
116
+ `test/regression/FulfillmentBlocksRatification.t.sol`
117
+ - pending reserve effects on completion fairness:
118
+ `test/audit/PendingReserveSnapshotBypass.t.sol`
119
+
120
+ ## Source Map
121
+
122
+ - `src/DefifaDeployer.sol`
123
+ - `src/DefifaGovernor.sol`
124
+ - `src/DefifaHook.sol`
125
+ - `src/libraries/DefifaHookLib.sol`
126
+ - `src/DefifaTokenUriResolver.sol`
127
+ - `test/DefifaGovernor.t.sol`
128
+ - `test/DefifaHookRegressions.t.sol`
129
+ - `test/DefifaFeeAccounting.t.sol`
130
+ - `test/regression/FulfillmentBlocksRatification.t.sol`
131
+ - `test/audit/PendingReserveSnapshotBypass.t.sol`
@@ -1,96 +1,94 @@
1
1
  # Audit Instructions
2
2
 
3
- Defifa is a staged prediction-game system built on Juicebox and the 721 hook stack. The main risks are governance correctness, treasury settlement, and cash-out weight integrity.
3
+ Defifa is a staged prediction-game system built on Juicebox and the tiered 721 stack. Audit it as a governance-and-settlement protocol, not just an NFT game.
4
4
 
5
- ## Objective
5
+ ## Audit Objective
6
6
 
7
7
  Find issues that:
8
+
8
9
  - let players extract more than their fair share of the game pot
9
- - break the game-phase lifecycle or let actions occur in the wrong phase
10
- - corrupt scorecard submission, attestation, quorum, grace-period, or ratification logic
10
+ - break the game-phase lifecycle or allow actions in the wrong phase
11
+ - corrupt scorecard submission, attestation, quorum, delegation, grace-period, or ratification logic
11
12
  - miscompute tier cash-out weights or fee-token distribution
12
- - let deployment or ownership helpers leave a game misconfigured
13
+ - leave a deployed game misconfigured through deployer or owner-helper mistakes
13
14
 
14
15
  ## Scope
15
16
 
16
17
  In scope:
18
+
17
19
  - `src/DefifaDeployer.sol`
18
20
  - `src/DefifaGovernor.sol`
19
21
  - `src/DefifaHook.sol`
20
22
  - `src/DefifaProjectOwner.sol`
21
23
  - `src/DefifaTokenUriResolver.sol`
22
24
  - `src/libraries/DefifaHookLib.sol`
23
- - `src/interfaces/`, `src/structs/`, and `src/enums/`
24
- - deployment scripts in `script/`
25
+ - enums, interfaces, structs, and deployment helpers
26
+
27
+ ## Start Here
25
28
 
26
- Key integrations:
27
- - `nana-core-v6`
28
- - `nana-721-hook-v6`
29
- - deployer and ownership helper patterns shared across the ecosystem
29
+ 1. `src/DefifaGovernor.sol`
30
+ 2. `src/DefifaHook.sol`
31
+ 3. `src/DefifaDeployer.sol`
32
+ 4. `src/DefifaProjectOwner.sol`
30
33
 
31
- ## System Model
34
+ ## Security Model
32
35
 
33
36
  High-level lifecycle:
37
+
34
38
  - deploy a game as a Juicebox project
35
- - sell outcome NFTs during mint phase
39
+ - sell outcome NFTs during the mint phase
36
40
  - optionally allow refunds or no-contest handling
37
41
  - run scorecard governance through submissions and attestations
38
- - ratify a scorecard
42
+ - ratify one scorecard
39
43
  - update cash-out weights so winning pieces can redeem the treasury
40
44
 
41
45
  The contracts split responsibility as follows:
42
- - `DefifaDeployer`: project launch and lifecycle orchestration
43
- - `DefifaHook`: minting, burning, and game-specific cash-out accounting
44
- - `DefifaGovernor`: scorecard governance and ratification
45
- - `DefifaTokenUriResolver`: game NFT metadata
46
-
47
- ## Critical Invariants
48
46
 
49
- 1. Pot conservation
50
- Total redeemable value across all settled tiers must not exceed the game treasury after applying intended fees.
47
+ - `DefifaDeployer` launches the project and wires lifecycle configuration
48
+ - `DefifaHook` handles minting, burning, fee accounting, and game-specific cash-out math
49
+ - `DefifaGovernor` owns scorecard governance and ratification
50
+ - `DefifaProjectOwner` acts as a project-owner helper where governance needs a stable admin surface
51
+ - `DefifaTokenUriResolver` handles game NFT metadata
51
52
 
52
- 2. Governance phase safety
53
- Submission, attestation, ratification, no-contest, and refund paths must be reachable only in the intended lifecycle windows.
53
+ ## Roles And Privileges
54
54
 
55
- 3. Quorum and grace-period correctness
56
- Attestation power, delegation, quorum thresholds, and grace-period timing must not be manipulable to ratify an invalid scorecard early or indefinitely block a valid one.
55
+ | Role | Powers | How constrained |
56
+ |------|--------|-----------------|
57
+ | Game deployer or owner path | Configure a game's initial lifecycle and helper wiring | Must not retain hidden post-launch powers |
58
+ | Governor participants | Submit, attest to, and ratify scorecards | Must remain bounded by phase, quorum, and delegation rules |
59
+ | `DefifaHook` | Determine mint and final redeem economics | Must not over-credit players or under-account fees |
60
+ | Project owner helper | Stand in for project ownership where configured | Must not diverge from the intended governance authority |
57
61
 
58
- 4. Settlement determinism
59
- Once the winning scorecard is finalized, the resulting cash-out weights must match the intended outcome and remain internally consistent.
62
+ ## Integration Assumptions
60
63
 
61
- 5. No fee-token dilution bugs
62
- Fee accounting and reserve-related side effects must not dilute players or over-credit non-paying participants.
64
+ | Dependency | Assumption | What breaks if wrong |
65
+ |------------|------------|----------------------|
66
+ | `nana-core-v6` | Treasury accounting, rulesets, and cash-out surfaces stay coherent | Pot settlement and redeem math become unsound |
67
+ | `nana-721-hook-v6` | Tier issuance and reserve behavior match Defifa's game logic | Voting power, supply, and cash-out weights drift |
68
+ | Owner-helper and deployer patterns | Launch-time authority fully converges to the intended game authority | Games remain misconfigured or over-privileged |
63
69
 
64
- ## Threat Model
70
+ ## Critical Invariants
65
71
 
66
- Prioritize:
67
- - whale participants trying to dominate attestation power
68
- - players exploiting pending reserves, delegation, or snapshot timing
69
- - callers trying to ratify with partially completed commitments
70
- - phase-boundary and timestamp races
71
- - settlement paths that assume external payout success
72
+ 1. Pot conservation.
73
+ 2. Governance phase safety.
74
+ 3. Quorum and grace-period correctness.
75
+ 4. Settlement determinism once a scorecard is final.
76
+ 5. Fee-token and reserve correctness.
72
77
 
73
- ## Hotspots
78
+ ## Attack Surfaces
74
79
 
75
- - `DefifaGovernor` scorecard state transitions
80
+ - `DefifaGovernor` scorecard state transitions and ratification gating
81
+ - delegation, attestation, and quorum calculations
76
82
  - `DefifaHook` cash-out weight and fee-token accounting
77
83
  - reserve-related denominators during governance and settlement
78
84
  - deployer logic that queues or fulfills lifecycle rulesets
79
- - any low-level call used during ratification or fulfillment
80
- - token URI or metadata logic only insofar as it can desync governance or settlement assumptions
81
85
 
82
- ## Build And Verification
86
+ ## Accepted Risks Or Behaviors
87
+
88
+ - Governance and settlement are intentionally phase-heavy, so timestamp and lifecycle transitions are core audit targets rather than edge cases.
89
+
90
+ ## Verification
83
91
 
84
- Standard workflow:
85
92
  - `npm install`
86
93
  - `forge build`
87
94
  - `forge test`
88
-
89
- The current tests focus on:
90
- - quorum hardening
91
- - no-contest and refund handling
92
- - pending reserve dilution
93
- - fee accounting
94
- - regressions around attestation delegation and grace-period bypass
95
-
96
- The best findings in this repo usually demonstrate either treasury over-redemption or a governance state transition that should be impossible.