@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 +55 -142
- package/ARCHITECTURE.md +109 -45
- package/AUDIT_INSTRUCTIONS.md +50 -52
- package/README.md +97 -32
- package/RISKS.md +41 -50
- package/SKILLS.md +18 -14
- package/USER_JOURNEYS.md +142 -42
- package/foundry.toml +2 -0
- package/package.json +6 -6
- package/references/operations.md +6 -1
- package/references/runtime.md +15 -4
- package/src/DefifaDeployer.sol +3 -0
- package/src/DefifaHook.sol +5 -0
- package/src/structs/DefifaTierParams.sol +0 -1
- package/test/audit/CodexTierCapMismatch.t.sol +171 -0
- package/test/audit/H5TierCapValidation.t.sol +184 -0
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 |
|
|
10
|
-
|
|
|
11
|
-
| Highest-risk actions | Launching
|
|
12
|
-
| Recovery posture |
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
16
|
+
## Control Model
|
|
28
17
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
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 |
|
|
35
|
-
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
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
|
-
##
|
|
143
|
-
|
|
144
|
-
What admins CANNOT do:
|
|
34
|
+
## Privileged Surfaces
|
|
145
35
|
|
|
146
|
-
|
|
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
|
-
|
|
41
|
+
## Immutable And One-Way
|
|
149
42
|
|
|
150
|
-
|
|
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
|
-
|
|
50
|
+
## Operational Notes
|
|
153
51
|
|
|
154
|
-
|
|
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
|
-
|
|
58
|
+
## Machine Notes
|
|
157
59
|
|
|
158
|
-
|
|
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
|
-
|
|
65
|
+
## Recovery
|
|
161
66
|
|
|
162
|
-
|
|
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
|
-
|
|
72
|
+
## Admin Boundaries
|
|
165
73
|
|
|
166
|
-
|
|
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
|
|
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
|
-
##
|
|
7
|
+
## System Overview
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
##
|
|
11
|
+
## Core Invariants
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
##
|
|
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
|
-
->
|
|
30
|
-
|
|
31
|
-
->
|
|
32
|
-
|
|
33
|
-
->
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
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
|
-
|
|
90
|
+
The hook's completion math is intentionally phase-sensitive:
|
|
50
91
|
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
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
|
-
##
|
|
96
|
+
## Security Model
|
|
56
97
|
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
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
|
-
-
|
|
64
|
-
- If
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
|
|
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`
|
package/AUDIT_INSTRUCTIONS.md
CHANGED
|
@@ -1,96 +1,94 @@
|
|
|
1
1
|
# Audit Instructions
|
|
2
2
|
|
|
3
|
-
Defifa is a staged prediction-game system built on Juicebox and the 721
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
24
|
-
|
|
25
|
+
- enums, interfaces, structs, and deployment helpers
|
|
26
|
+
|
|
27
|
+
## Start Here
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
1. `src/DefifaGovernor.sol`
|
|
30
|
+
2. `src/DefifaHook.sol`
|
|
31
|
+
3. `src/DefifaDeployer.sol`
|
|
32
|
+
4. `src/DefifaProjectOwner.sol`
|
|
30
33
|
|
|
31
|
-
##
|
|
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
|
|
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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
|
|
62
|
-
|
|
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
|
-
##
|
|
70
|
+
## Critical Invariants
|
|
65
71
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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.
|