@ballkidz/defifa 0.0.4 → 0.0.6
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/RISKS.md +7 -7
- package/STYLE_GUIDE.md +130 -61
- package/foundry.toml +0 -10
- package/package.json +6 -6
- package/remappings.txt +0 -5
- package/script/Deploy.s.sol +1 -1
- package/script/helpers/DefifaDeploymentLib.sol +1 -1
- package/src/DefifaDeployer.sol +1 -1
- package/src/DefifaHook.sol +1 -0
- package/src/interfaces/IDefifaDeployer.sol +0 -1
- package/src/interfaces/IDefifaGovernor.sol +0 -1
- package/src/interfaces/IDefifaTokenUriResolver.sol +0 -2
- package/src/structs/DefifaLaunchProjectData.sol +0 -2
- package/test/DefifaFeeAccounting.t.sol +4 -4
- package/test/DefifaGovernor.t.sol +6 -12
- package/test/{DefifaHook_AuditFindings.t.sol → DefifaHookRegressions.t.sol} +5 -5
- package/test/DefifaNoContest.t.sol +1 -1
- package/test/DefifaSecurity.t.sol +1 -1
- package/test/DefifaUSDC.t.sol +470 -0
- package/test/Fork.t.sol +70 -81
- package/test/regression/{M36_FulfillmentBlocksRatification.t.sol → FulfillmentBlocksRatification.t.sol} +3 -3
- package/test/regression/{M35_GracePeriodBypass.t.sol → GracePeriodBypass.t.sol} +3 -3
package/RISKS.md
CHANGED
|
@@ -101,7 +101,7 @@ Deep implementation-level risk analysis with line references, severity ratings,
|
|
|
101
101
|
|
|
102
102
|
**Severity:** MEDIUM
|
|
103
103
|
**Status:** BY DESIGN
|
|
104
|
-
**Tested:** `DefifaSecurityTest.testM_D6_delegationBlocked`, `
|
|
104
|
+
**Tested:** `DefifaSecurityTest.testM_D6_delegationBlocked`, `DefifaHookRegressions.test_M5_attestationUnitsPreservedOnTransferToUndelegatedRecipient`
|
|
105
105
|
|
|
106
106
|
**Description:** `setTierDelegateTo` and `setTierDelegatesTo` only work during MINT phase (DefifaHook lines 730, 740). After MINT, NFT transfers auto-delegate to the recipient (if no delegate set), but holders cannot explicitly re-delegate.
|
|
107
107
|
|
|
@@ -140,7 +140,7 @@ Deep implementation-level risk analysis with line references, severity ratings,
|
|
|
140
140
|
|
|
141
141
|
**Severity:** LOW
|
|
142
142
|
**Status:** MITIGATED
|
|
143
|
-
**Tested:** `
|
|
143
|
+
**Tested:** `FulfillmentBlocksRatification.test_ratificationSucceedsWhenFulfillmentReverts`
|
|
144
144
|
|
|
145
145
|
**Description:** `ratifyScorecardFrom` wraps `fulfillCommitmentsOf` in a try-catch (DefifaGovernor lines 402-405). If fulfillment fails (e.g., `sendPayoutsOf` reverts), the scorecard is still ratified and `FulfillmentFailed` event is emitted.
|
|
146
146
|
|
|
@@ -154,7 +154,7 @@ Deep implementation-level risk analysis with line references, severity ratings,
|
|
|
154
154
|
|
|
155
155
|
**Severity:** LOW
|
|
156
156
|
**Status:** FIXED (Regression tested)
|
|
157
|
-
**Tested:** `
|
|
157
|
+
**Tested:** `GracePeriodBypass.test_gracePeriodExtendsFromAttestationStart`
|
|
158
158
|
|
|
159
159
|
**Description:** When a scorecard is submitted before `attestationStartTime`, the grace period could previously expire before attestations even begin. Fixed by anchoring `gracePeriodEnds` to `attestationsBegin` rather than submission time.
|
|
160
160
|
|
|
@@ -245,7 +245,7 @@ Deep implementation-level risk analysis with line references, severity ratings,
|
|
|
245
245
|
|
|
246
246
|
**Severity:** HIGH (before fix)
|
|
247
247
|
**Status:** FIXED
|
|
248
|
-
**Tested:** `
|
|
248
|
+
**Tested:** `DefifaHookRegressions.test_M5_attestationUnitsPreservedOnTransferToUndelegatedRecipient`, `test_M5_multipleTransfersToUndelegatedRecipientsPreserveUnits`
|
|
249
249
|
|
|
250
250
|
**Description:** Previously, transferring an NFT to a recipient with no delegate set would lose attestation units (sender's delegate lost units but no one gained them). Fixed by auto-delegating undelegated recipients to themselves in `_transferTierAttestationUnits` (DefifaHook lines 1001-1006).
|
|
251
251
|
|
|
@@ -314,15 +314,15 @@ Deep implementation-level risk analysis with line references, severity ratings,
|
|
|
314
314
|
| RISK-6 Delegation locked | `DefifaSecurity.t.sol` | `testM_D6_delegationBlocked` |
|
|
315
315
|
| RISK-7 Single governor | (No isolation test) | Design review only |
|
|
316
316
|
| RISK-8 Clone front-running | (Implicit) | All `launchGameWith` tests |
|
|
317
|
-
| RISK-9 Fulfillment failure | `regression/
|
|
318
|
-
| RISK-10 Grace period bypass | `regression/
|
|
317
|
+
| RISK-9 Fulfillment failure | `regression/FulfillmentBlocksRatification.t.sol` | `test_ratificationSucceedsWhenFulfillmentReverts` |
|
|
318
|
+
| RISK-10 Grace period bypass | `regression/GracePeriodBypass.t.sol` | `test_gracePeriodExtendsFromAttestationStart` |
|
|
319
319
|
| RISK-11 Overweight scorecard | `DefifaSecurity.t.sol` | `testC_D2_rejectsOverweight` |
|
|
320
320
|
| RISK-12 No-contest trigger | `DefifaNoContest.t.sol` | `testNoContest_cashOutBeforeTrigger_reverts`, `testTriggerNoContest_revertsWhenNotNoContest`, `testTriggerNoContest_revertsWhenAlreadyTriggered` |
|
|
321
321
|
| RISK-13 `_totalMintCost` | `DefifaMintCostInvariant.t.sol` | `invariant_totalMintCostMatchesExpected`, `invariant_totalMintCostEqualsPriceTimesLiveTokens`, `invariant_tokenCountConsistency` |
|
|
322
322
|
| RISK-14 Fee accounting | `DefifaFeeAccounting.t.sol` | All 6 tests |
|
|
323
323
|
| RISK-15 Cash-out reentrancy | (Code review) | State ordering analysis |
|
|
324
324
|
| RISK-16 Fulfillment reentrancy | (Code review) | Guard analysis |
|
|
325
|
-
| RISK-17 Attestation conservation | `
|
|
325
|
+
| RISK-17 Attestation conservation | `DefifaHookRegressions.t.sol` | `test_M5_attestationUnitsPreservedOnTransferToUndelegatedRecipient`, `test_M5_multipleTransfersToUndelegatedRecipientsPreserveUnits` |
|
|
326
326
|
| RISK-18 Fund conservation | `DefifaSecurity.t.sol` | `testFuzz_fundConservation`, `testHighVolume_32tiers`, `testMultiPlayer_winnerTakesAll`, `testRefundIntegrity` |
|
|
327
327
|
| RISK-19 uint208 overflow | (Bounded analysis) | Arithmetic review |
|
|
328
328
|
| RISK-20 Timestamp caching | (Test infrastructure) | `TimestampReader` pattern |
|
package/STYLE_GUIDE.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
How we write Solidity and organize repos across the Juicebox V6 ecosystem. `nana-core-v6` is the gold standard — when in doubt, match what it does.
|
|
4
4
|
|
|
5
|
-
**This repo's deviations:** `via-ir = true`, `build_info = true`, `extra_output = ['storageLayout']`. Lower invariant runs (256/depth 50). Package scope: `@ballkidz/`.
|
|
6
|
-
|
|
7
5
|
## File Organization
|
|
8
6
|
|
|
9
7
|
```
|
|
@@ -19,8 +17,6 @@ src/
|
|
|
19
17
|
|
|
20
18
|
One contract/interface/struct/enum per file. Name the file after the type it contains.
|
|
21
19
|
|
|
22
|
-
**Structs, enums, libraries, and interfaces always go in their subdirectories** (`src/structs/`, `src/enums/`, `src/libraries/`, `src/interfaces/`) — never inline in contract files or placed in `src/` root. This keeps type definitions discoverable and import paths consistent across repos.
|
|
23
|
-
|
|
24
20
|
## Pragma Versions
|
|
25
21
|
|
|
26
22
|
```solidity
|
|
@@ -108,14 +104,6 @@ contract JBExample is JBPermissioned, IJBExample {
|
|
|
108
104
|
// -------------------------- constructor ---------------------------- //
|
|
109
105
|
//*********************************************************************//
|
|
110
106
|
|
|
111
|
-
//*********************************************************************//
|
|
112
|
-
// ---------------------- receive / fallback ------------------------- //
|
|
113
|
-
//*********************************************************************//
|
|
114
|
-
|
|
115
|
-
//*********************************************************************//
|
|
116
|
-
// --------------------------- modifiers ----------------------------- //
|
|
117
|
-
//*********************************************************************//
|
|
118
|
-
|
|
119
107
|
//*********************************************************************//
|
|
120
108
|
// ---------------------- external transactions ---------------------- //
|
|
121
109
|
//*********************************************************************//
|
|
@@ -143,28 +131,23 @@ contract JBExample is JBPermissioned, IJBExample {
|
|
|
143
131
|
```
|
|
144
132
|
|
|
145
133
|
**Section order:**
|
|
146
|
-
1.
|
|
147
|
-
2.
|
|
148
|
-
3.
|
|
149
|
-
4.
|
|
150
|
-
5.
|
|
151
|
-
6.
|
|
152
|
-
7.
|
|
153
|
-
8.
|
|
154
|
-
9.
|
|
155
|
-
10.
|
|
156
|
-
11.
|
|
157
|
-
12.
|
|
158
|
-
13.
|
|
159
|
-
14.
|
|
160
|
-
15. Internal helpers
|
|
161
|
-
16. Internal views
|
|
162
|
-
17. Private helpers
|
|
134
|
+
1. Custom errors
|
|
135
|
+
2. Public constants
|
|
136
|
+
3. Internal constants
|
|
137
|
+
4. Public immutable stored properties
|
|
138
|
+
5. Internal immutable stored properties
|
|
139
|
+
6. Public stored properties
|
|
140
|
+
7. Internal stored properties
|
|
141
|
+
8. Constructor
|
|
142
|
+
9. External transactions
|
|
143
|
+
10. External views
|
|
144
|
+
11. Public transactions
|
|
145
|
+
12. Internal helpers
|
|
146
|
+
13. Internal views
|
|
147
|
+
14. Private helpers
|
|
163
148
|
|
|
164
149
|
Functions are alphabetized within each section.
|
|
165
150
|
|
|
166
|
-
**Events:** Events are declared in interfaces only, never in implementation contracts. Implementations inherit events from their interface and emit them unqualified. This keeps the ABI definition in one place and allows tests to use interface-qualified event expectations (e.g., `emit IJBController.LaunchProject(...)`).
|
|
167
|
-
|
|
168
151
|
## Interface Structure
|
|
169
152
|
|
|
170
153
|
```solidity
|
|
@@ -336,9 +319,6 @@ optimizer_runs = 200
|
|
|
336
319
|
libs = ["node_modules", "lib"]
|
|
337
320
|
fs_permissions = [{ access = "read-write", path = "./"}]
|
|
338
321
|
|
|
339
|
-
[profile.ci_sizes]
|
|
340
|
-
optimizer_runs = 200
|
|
341
|
-
|
|
342
322
|
[fuzz]
|
|
343
323
|
runs = 4096
|
|
344
324
|
|
|
@@ -353,18 +333,14 @@ multiline_func_header = "all"
|
|
|
353
333
|
wrap_comments = true
|
|
354
334
|
```
|
|
355
335
|
|
|
356
|
-
**
|
|
357
|
-
- `
|
|
358
|
-
- `
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
- `
|
|
363
|
-
- `
|
|
364
|
-
- `[rpc_endpoints]` for ethereum, optimism, arbitrum, base, and their testnets
|
|
365
|
-
- `[invariant]` with `runs = 256`, `depth = 50` (lower than standard)
|
|
366
|
-
- No `[fuzz]` section
|
|
367
|
-
- `[lint]` section with `lint_on_build = false`
|
|
336
|
+
**Optional sections (add only when needed):**
|
|
337
|
+
- `[rpc_endpoints]` — repos with fork tests. Maps named endpoints to env vars (e.g. `ethereum = "${RPC_ETHEREUM_MAINNET}"`).
|
|
338
|
+
- `[profile.ci_sizes]` — only when CI needs different optimizer settings than defaults for the size check step (e.g. `optimizer_runs = 200` when the default profile uses a lower value).
|
|
339
|
+
|
|
340
|
+
**Common variations:**
|
|
341
|
+
- `via_ir = true` when hitting stack-too-deep
|
|
342
|
+
- `optimizer = false` when optimization causes stack-too-deep
|
|
343
|
+
- `optimizer_runs` reduced when deep struct nesting causes stack-too-deep at 200 runs
|
|
368
344
|
|
|
369
345
|
### CI Workflows
|
|
370
346
|
|
|
@@ -397,7 +373,7 @@ jobs:
|
|
|
397
373
|
env:
|
|
398
374
|
RPC_ETHEREUM_MAINNET: ${{ secrets.RPC_ETHEREUM_MAINNET }}
|
|
399
375
|
- name: Check contract sizes
|
|
400
|
-
run:
|
|
376
|
+
run: forge build --sizes --skip "*/test/**" --skip "*/script/**" --skip SphinxUtils
|
|
401
377
|
```
|
|
402
378
|
|
|
403
379
|
**lint.yml:**
|
|
@@ -419,11 +395,60 @@ jobs:
|
|
|
419
395
|
run: forge fmt --check
|
|
420
396
|
```
|
|
421
397
|
|
|
398
|
+
**slither.yml** (repos with `src/` contracts only):
|
|
399
|
+
```yaml
|
|
400
|
+
name: slither
|
|
401
|
+
on:
|
|
402
|
+
pull_request:
|
|
403
|
+
branches:
|
|
404
|
+
- main
|
|
405
|
+
push:
|
|
406
|
+
branches:
|
|
407
|
+
- main
|
|
408
|
+
jobs:
|
|
409
|
+
analyze:
|
|
410
|
+
runs-on: ubuntu-latest
|
|
411
|
+
steps:
|
|
412
|
+
- uses: actions/checkout@v4
|
|
413
|
+
with:
|
|
414
|
+
submodules: recursive
|
|
415
|
+
- uses: actions/setup-node@v4
|
|
416
|
+
with:
|
|
417
|
+
node-version: latest
|
|
418
|
+
- name: Install npm dependencies
|
|
419
|
+
run: npm install --omit=dev
|
|
420
|
+
- name: Install Foundry
|
|
421
|
+
uses: foundry-rs/foundry-toolchain@v1
|
|
422
|
+
- name: Run slither
|
|
423
|
+
uses: crytic/slither-action@v0.3.1
|
|
424
|
+
with:
|
|
425
|
+
slither-config: slither-ci.config.json
|
|
426
|
+
fail-on: medium
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**slither-ci.config.json:**
|
|
430
|
+
```json
|
|
431
|
+
{
|
|
432
|
+
"detectors_to_exclude": "timestamp,uninitialized-local,naming-convention,solc-version,shadowing-local",
|
|
433
|
+
"exclude_informational": true,
|
|
434
|
+
"exclude_low": false,
|
|
435
|
+
"exclude_medium": false,
|
|
436
|
+
"exclude_high": false,
|
|
437
|
+
"disable_color": false,
|
|
438
|
+
"filter_paths": "(mocks/|test/|node_modules/|lib/)",
|
|
439
|
+
"legacy_ast": false
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Variations:**
|
|
444
|
+
- Deployer-only repos (no `src/`, only `script/`) skip slither entirely — the action's internal `forge build` skips `test/` and `script/` by default, leaving nothing to compile.
|
|
445
|
+
- Use inline `// slither-disable-next-line <detector>` to suppress known false positives rather than adding to `detectors_to_exclude` in the config. The comment must be on the line immediately before the flagged expression.
|
|
446
|
+
|
|
422
447
|
### package.json
|
|
423
448
|
|
|
424
449
|
```json
|
|
425
450
|
{
|
|
426
|
-
"name": "@
|
|
451
|
+
"name": "@bananapus/package-name-v6",
|
|
427
452
|
"version": "x.x.x",
|
|
428
453
|
"license": "MIT",
|
|
429
454
|
"repository": { "type": "git", "url": "git+https://github.com/Org/repo.git" },
|
|
@@ -443,13 +468,62 @@ jobs:
|
|
|
443
468
|
|
|
444
469
|
### remappings.txt
|
|
445
470
|
|
|
446
|
-
Every repo has a `remappings.txt
|
|
471
|
+
Every repo has a `remappings.txt` as the **single source of truth** for import remappings. Never add remappings to `foundry.toml`.
|
|
472
|
+
|
|
473
|
+
**Principle:** Import paths in Solidity source must match npm package names exactly. With `libs = ["node_modules", "lib"]`, Foundry auto-resolves `@scope/package/path/File.sol` → `node_modules/@scope/package/path/File.sol`. No remapping needed for packages installed as real directories.
|
|
474
|
+
|
|
475
|
+
**Note:** Auto-resolution does **not** work for symlinked packages (e.g. npm workspace links). Workspace repos like `deploy-all-v6` and `nana-cli-v6` need explicit `@scope/package/=node_modules/@scope/package/` remappings for each symlinked dependency.
|
|
476
|
+
|
|
477
|
+
**Minimal content** (most repos):
|
|
447
478
|
|
|
448
479
|
```
|
|
449
|
-
|
|
480
|
+
forge-std/=lib/forge-std/src/
|
|
450
481
|
```
|
|
451
482
|
|
|
452
|
-
|
|
483
|
+
Only add extra remappings for:
|
|
484
|
+
- **`forge-std`** — always needed (git submodule with `src/` subdirectory)
|
|
485
|
+
- **Repo-specific `lib/` submodules** that have no npm package (e.g., `hookmate/=lib/hookmate/src/`)
|
|
486
|
+
- **Symlinked npm packages** — need explicit `@scope/package/=node_modules/@scope/package/` entries
|
|
487
|
+
- **Nested transitive deps** — e.g., `@chainlink/contracts-ccip/` nested inside `@bananapus/suckers-v6/node_modules/`
|
|
488
|
+
|
|
489
|
+
**Never add remappings for:**
|
|
490
|
+
- npm packages that match their import path and are installed as real directories — they auto-resolve
|
|
491
|
+
- Short-form aliases (e.g., `@bananapus/core/` → `@bananapus/core-v6/src/`) — fix the import instead
|
|
492
|
+
- Packages available via npm that are also git submodules — remove the submodule, use npm
|
|
493
|
+
|
|
494
|
+
**Import path convention:**
|
|
495
|
+
|
|
496
|
+
| Package | Import path | Resolves to |
|
|
497
|
+
|---------|------------|-------------|
|
|
498
|
+
| `@bananapus/core-v6` | `@bananapus/core-v6/src/libraries/JBConstants.sol` | `node_modules/@bananapus/core-v6/src/...` |
|
|
499
|
+
| `@openzeppelin/contracts` | `@openzeppelin/contracts/token/ERC20/IERC20.sol` | `node_modules/@openzeppelin/contracts/...` |
|
|
500
|
+
| `@uniswap/v4-core` | `@uniswap/v4-core/src/interfaces/IPoolManager.sol` | `node_modules/@uniswap/v4-core/src/...` |
|
|
501
|
+
|
|
502
|
+
### Linting
|
|
503
|
+
|
|
504
|
+
Solar (Foundry's built-in linter) runs automatically during `forge build`. It scans all `.sol` files in `libs` directories, including `node_modules`.
|
|
505
|
+
|
|
506
|
+
**All test helpers must use relative imports** (e.g. `../../src/structs/JBRuleset.sol`), not bare `src/` imports. This ensures solar can resolve paths when the helper is consumed via npm in downstream repos.
|
|
507
|
+
|
|
508
|
+
### Fork Tests
|
|
509
|
+
|
|
510
|
+
Fork tests use named RPC endpoints defined in `[rpc_endpoints]` of `foundry.toml`. No skip guards — fork tests should hard-fail if the RPC endpoint is unavailable, making CI failures explicit.
|
|
511
|
+
|
|
512
|
+
```solidity
|
|
513
|
+
function setUp() public {
|
|
514
|
+
vm.createSelectFork("ethereum");
|
|
515
|
+
// ... setup code
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
The endpoint name (e.g. `"ethereum"`) maps to an env var via `foundry.toml`:
|
|
520
|
+
|
|
521
|
+
```toml
|
|
522
|
+
[rpc_endpoints]
|
|
523
|
+
ethereum = "${RPC_ETHEREUM_MAINNET}"
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
For multi-chain fork tests, add all needed endpoints.
|
|
453
527
|
|
|
454
528
|
### Formatting
|
|
455
529
|
|
|
@@ -460,15 +534,6 @@ Run `forge fmt` before committing. The `[fmt]` config in `foundry.toml` enforces
|
|
|
460
534
|
|
|
461
535
|
CI checks formatting via `forge fmt --check`.
|
|
462
536
|
|
|
463
|
-
### CI Secrets
|
|
464
|
-
|
|
465
|
-
| Secret | Purpose |
|
|
466
|
-
|--------|--------|
|
|
467
|
-
| `NPM_TOKEN` | npm publish access (used by `publish.yml`) |
|
|
468
|
-
| `RPC_ETHEREUM_MAINNET` | Ethereum mainnet RPC URL for fork tests (used by `test.yml`) |
|
|
469
|
-
|
|
470
|
-
Fork tests require `RPC_ETHEREUM_MAINNET` — they fail if it's missing.
|
|
471
|
-
|
|
472
537
|
### Branching
|
|
473
538
|
|
|
474
539
|
- `main` is the primary branch
|
|
@@ -486,4 +551,8 @@ Fork tests require `RPC_ETHEREUM_MAINNET` — they fail if it's missing.
|
|
|
486
551
|
|
|
487
552
|
### Contract Size Checks
|
|
488
553
|
|
|
489
|
-
CI runs `
|
|
554
|
+
CI runs `forge build --sizes` to catch contracts approaching the 24KB limit. When the repo's default `optimizer_runs` differs from what you want for size checking, use `FOUNDRY_PROFILE=ci_sizes forge build --sizes` with a `[profile.ci_sizes]` section in `foundry.toml`.
|
|
555
|
+
|
|
556
|
+
## Repo-Specific Deviations
|
|
557
|
+
|
|
558
|
+
None. This repo follows the standard configuration exactly.
|
package/foundry.toml
CHANGED
|
@@ -6,18 +6,8 @@ optimizer_runs = 200
|
|
|
6
6
|
libs = ["node_modules", "lib"]
|
|
7
7
|
fs_permissions = [{ access = "read-write", path = "./"}]
|
|
8
8
|
|
|
9
|
-
[profile.ci_sizes]
|
|
10
|
-
optimizer_runs = 200
|
|
11
|
-
|
|
12
9
|
[rpc_endpoints]
|
|
13
10
|
ethereum = "${RPC_ETHEREUM_MAINNET}"
|
|
14
|
-
optimism = "${RPC_OPTIMISM_MAINNET}"
|
|
15
|
-
arbitrum = "${RPC_ARBITRUM_MAINNET}"
|
|
16
|
-
base = "${RPC_BASE_MAINNET}"
|
|
17
|
-
arbitrum_sepolia = "${RPC_ARBITRUM_SEPOLIA}"
|
|
18
|
-
ethereum_sepolia = "${RPC_ETHEREUM_SEPOLIA}"
|
|
19
|
-
optimism_sepolia = "${RPC_OPTIMISM_SEPOLIA}"
|
|
20
|
-
base_sepolia = "${RPC_BASE_SEPOLIA}"
|
|
21
11
|
|
|
22
12
|
[fuzz]
|
|
23
13
|
runs = 4096
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ballkidz/defifa",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0"
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"url": "https://github.com/BallKidz/defifa-collection-deployer"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@bananapus/721-hook-v6": "^0.0.
|
|
17
|
-
"@bananapus/address-registry-v6": "^0.0.
|
|
18
|
-
"@bananapus/core-v6": "^0.0.
|
|
19
|
-
"@bananapus/permission-ids-v6": "^0.0.
|
|
20
|
-
"@openzeppelin/contracts": "5.
|
|
16
|
+
"@bananapus/721-hook-v6": "^0.0.14",
|
|
17
|
+
"@bananapus/address-registry-v6": "^0.0.8",
|
|
18
|
+
"@bananapus/core-v6": "^0.0.15",
|
|
19
|
+
"@bananapus/permission-ids-v6": "^0.0.8",
|
|
20
|
+
"@openzeppelin/contracts": "^5.6.1",
|
|
21
21
|
"@prb/math": "^4.1.1",
|
|
22
22
|
"scripty.sol": "^2.1.1"
|
|
23
23
|
},
|
package/remappings.txt
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
@openzeppelin/=node_modules/@openzeppelin/
|
|
2
|
-
@prb/math/=node_modules/@prb/math/
|
|
3
|
-
@bananapus/=node_modules/@bananapus/
|
|
4
|
-
@sphinx-labs/contracts/=node_modules/@sphinx-labs/contracts/contracts/foundry/
|
|
5
1
|
forge-std/=lib/forge-std/src/
|
|
6
|
-
scripty.sol/=node_modules/scripty.sol/
|
package/script/Deploy.s.sol
CHANGED
|
@@ -9,7 +9,7 @@ import {DefifaDeployer} from "../src/DefifaDeployer.sol";
|
|
|
9
9
|
import {DefifaGovernor} from "../src/DefifaGovernor.sol";
|
|
10
10
|
import {DefifaProjectOwner} from "../src/DefifaProjectOwner.sol";
|
|
11
11
|
import {DefifaTokenUriResolver} from "../src/DefifaTokenUriResolver.sol";
|
|
12
|
-
import {Sphinx} from "@sphinx-labs/contracts/SphinxPlugin.sol";
|
|
12
|
+
import {Sphinx} from "@sphinx-labs/contracts/contracts/foundry/SphinxPlugin.sol";
|
|
13
13
|
|
|
14
14
|
import {CoreDeployment, CoreDeploymentLib} from "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
|
|
15
15
|
import {
|
|
@@ -9,7 +9,7 @@ import {DefifaDeployer} from "../../src/DefifaDeployer.sol";
|
|
|
9
9
|
import {DefifaGovernor} from "../../src/DefifaGovernor.sol";
|
|
10
10
|
import {DefifaTokenUriResolver} from "../../src/DefifaTokenUriResolver.sol";
|
|
11
11
|
|
|
12
|
-
import {SphinxConstants, NetworkInfo} from "@sphinx-labs/contracts/SphinxConstants.sol";
|
|
12
|
+
import {SphinxConstants, NetworkInfo} from "@sphinx-labs/contracts/contracts/foundry/SphinxConstants.sol";
|
|
13
13
|
|
|
14
14
|
struct DefifaDeployment {
|
|
15
15
|
DefifaHook hook;
|
package/src/DefifaDeployer.sol
CHANGED
|
@@ -411,8 +411,8 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
// Make sure the provided gameplay timestamps are sequential and that there is a mint duration.
|
|
414
|
-
// slither-disable-next-line incorrect-equality
|
|
415
414
|
if (
|
|
415
|
+
// slither-disable-next-line incorrect-equality
|
|
416
416
|
launchProjectData.mintPeriodDuration == 0
|
|
417
417
|
|| launchProjectData.start
|
|
418
418
|
< block.timestamp + launchProjectData.refundPeriodDuration + launchProjectData.mintPeriodDuration
|
package/src/DefifaHook.sol
CHANGED
|
@@ -532,6 +532,7 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
|
|
|
532
532
|
/// @notice Mint reserved tokens within the tier for the provided value.
|
|
533
533
|
/// @param tierId The ID of the tier to mint within.
|
|
534
534
|
/// @param count The number of reserved tokens to mint.
|
|
535
|
+
// slither-disable-next-line reentrancy-no-eth
|
|
535
536
|
function mintReservesFor(uint256 tierId, uint256 count) public override {
|
|
536
537
|
// Minting reserves must not be paused.
|
|
537
538
|
if (JB721TiersRulesetMetadataResolver.mintPendingReservesPaused(
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
4
|
import {DefifaLaunchProjectData} from "../structs/DefifaLaunchProjectData.sol";
|
|
5
|
-
import {DefifaOpsData} from "../structs/DefifaOpsData.sol";
|
|
6
5
|
import {IDefifaHook} from "./IDefifaHook.sol";
|
|
7
6
|
import {IDefifaGovernor} from "./IDefifaGovernor.sol";
|
|
8
7
|
|
|
@@ -3,7 +3,6 @@ pragma solidity 0.8.26;
|
|
|
3
3
|
|
|
4
4
|
import {DefifaScorecardState} from "../enums/DefifaScorecardState.sol";
|
|
5
5
|
import {DefifaTierCashOutWeight} from "../structs/DefifaTierCashOutWeight.sol";
|
|
6
|
-
import {IDefifaHook} from "./IDefifaHook.sol";
|
|
7
6
|
import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
|
|
8
7
|
|
|
9
8
|
/// @notice Manages the ratification of Defifa scorecards through attestation-based governance.
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
4
|
import {ITypeface} from "lib/typeface/contracts/interfaces/ITypeface.sol";
|
|
5
|
-
import {IDefifaHook} from "./IDefifaHook.sol";
|
|
6
|
-
import {IDefifaGamePhaseReporter} from "./IDefifaGamePhaseReporter.sol";
|
|
7
5
|
|
|
8
6
|
interface IDefifaTokenUriResolver {
|
|
9
7
|
function typeface() external view returns (ITypeface);
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
4
|
import {DefifaTierParams} from "./DefifaTierParams.sol";
|
|
5
|
-
import {DefifaOpsData} from "./DefifaOpsData.sol";
|
|
6
5
|
|
|
7
|
-
import {JBLaunchProjectConfig} from "@bananapus/721-hook-v6/src/structs/JBLaunchProjectConfig.sol";
|
|
8
6
|
import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
9
7
|
import {IJB721TiersHookStore} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHookStore.sol";
|
|
10
8
|
import {IJB721TokenUriResolver} from "@bananapus/721-hook-v6/src/interfaces/IJB721TokenUriResolver.sol";
|
|
@@ -463,7 +463,7 @@ contract DefifaFeeAccountingTest is JBTest, TestBaseWorkflow {
|
|
|
463
463
|
/// @notice Mint 1 NFT per tier, set delegation, return array of user addresses.
|
|
464
464
|
function _mintAllTiers(
|
|
465
465
|
DefifaHook _nft,
|
|
466
|
-
DefifaGovernor
|
|
466
|
+
DefifaGovernor,
|
|
467
467
|
uint256 projectId,
|
|
468
468
|
uint8 nTiers
|
|
469
469
|
)
|
|
@@ -499,7 +499,7 @@ contract DefifaFeeAccountingTest is JBTest, TestBaseWorkflow {
|
|
|
499
499
|
address[] memory users,
|
|
500
500
|
DefifaHook _nft,
|
|
501
501
|
DefifaGovernor _governor,
|
|
502
|
-
uint256
|
|
502
|
+
uint256,
|
|
503
503
|
uint8 nTiers
|
|
504
504
|
)
|
|
505
505
|
internal
|
|
@@ -541,7 +541,7 @@ contract DefifaFeeAccountingTest is JBTest, TestBaseWorkflow {
|
|
|
541
541
|
return (_tierId * 1_000_000_000) + _tokenNumber;
|
|
542
542
|
}
|
|
543
543
|
|
|
544
|
-
function _buildPayMetadata(bytes memory metadata) internal returns (bytes memory) {
|
|
544
|
+
function _buildPayMetadata(bytes memory metadata) internal view returns (bytes memory) {
|
|
545
545
|
bytes[] memory data = new bytes[](1);
|
|
546
546
|
data[0] = metadata;
|
|
547
547
|
bytes4[] memory ids = new bytes4[](1);
|
|
@@ -549,7 +549,7 @@ contract DefifaFeeAccountingTest is JBTest, TestBaseWorkflow {
|
|
|
549
549
|
return metadataHelper().createMetadata(ids, data);
|
|
550
550
|
}
|
|
551
551
|
|
|
552
|
-
function _buildCashOutMetadata(bytes memory metadata) internal returns (bytes memory) {
|
|
552
|
+
function _buildCashOutMetadata(bytes memory metadata) internal view returns (bytes memory) {
|
|
553
553
|
bytes[] memory data = new bytes[](1);
|
|
554
554
|
data[0] = metadata;
|
|
555
555
|
bytes4[] memory ids = new bytes4[](1);
|
|
@@ -444,8 +444,8 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
function testSetCashOutRatesAndRedeem_multipleTiers(uint8 nTiers, uint8[] calldata distribution) public {
|
|
447
|
-
|
|
448
|
-
vm.assume(distribution.length < nTiers);
|
|
447
|
+
nTiers = uint8(bound(uint256(nTiers), 11, 99));
|
|
448
|
+
vm.assume(distribution.length > 0 && distribution.length < nTiers);
|
|
449
449
|
|
|
450
450
|
uint256 _sumDistribution;
|
|
451
451
|
for (uint256 i = 0; i < distribution.length; i++) {
|
|
@@ -631,7 +631,6 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
631
631
|
JB721Tier memory _tier = _hook.store().tierOf(address(_hook), 1, false);
|
|
632
632
|
uint256 _cost = _tier.price;
|
|
633
633
|
|
|
634
|
-
address _delegateUser = address(bytes20(keccak256("_delegateUser")));
|
|
635
634
|
address _refundUser = address(bytes20(keccak256("refund_user")));
|
|
636
635
|
// The user should have no balance
|
|
637
636
|
assertEq(_hook.balanceOf(_refundUser), 0);
|
|
@@ -931,8 +930,6 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
931
930
|
_durationUntilProjectLaunch > 2 && _mintPeriodDuration > 1 && _inBetweenMintAndFifa > 1 && _fifaDuration > 1
|
|
932
931
|
);
|
|
933
932
|
uint48 _launchProjectAt = uint48(block.timestamp) + _durationUntilProjectLaunch;
|
|
934
|
-
uint48 _end =
|
|
935
|
-
_launchProjectAt + uint48(_mintPeriodDuration) + uint48(_inBetweenMintAndFifa) + uint48(_fifaDuration);
|
|
936
933
|
DefifaTierParams[] memory tierParams = new DefifaTierParams[](1);
|
|
937
934
|
tierParams[0] = DefifaTierParams({
|
|
938
935
|
reservedRate: 1001,
|
|
@@ -988,12 +985,10 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
988
985
|
|
|
989
986
|
function testWhenScorecardIsSubmittedWithUnmintedTier() public {
|
|
990
987
|
uint8 nTiers = 10;
|
|
991
|
-
address[] memory _users = new address[](nTiers);
|
|
992
988
|
DefifaLaunchProjectData memory defifaData = getBasicDefifaLaunchData(nTiers);
|
|
993
|
-
(
|
|
989
|
+
(,, DefifaGovernor _governor) = createDefifaProject(defifaData);
|
|
994
990
|
// Phase 1: Mint
|
|
995
991
|
vm.warp(defifaData.start - defifaData.mintPeriodDuration - defifaData.refundPeriodDuration);
|
|
996
|
-
//deployer.queueNextPhaseOf(_projectId);
|
|
997
992
|
|
|
998
993
|
// Warp to scoring phase (past start time)
|
|
999
994
|
vm.warp(defifaData.start + 1);
|
|
@@ -1007,7 +1002,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1007
1002
|
|
|
1008
1003
|
vm.expectRevert(abi.encodeWithSignature("DefifaGovernor_UnownedProposedCashoutValue()"));
|
|
1009
1004
|
// Forward time so proposals can be created
|
|
1010
|
-
|
|
1005
|
+
_governor.submitScorecardFor(_gameId, scorecards);
|
|
1011
1006
|
}
|
|
1012
1007
|
|
|
1013
1008
|
// function testWhenPhaseIsAlreadyQueued() public {
|
|
@@ -1256,7 +1251,6 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1256
1251
|
assertEq(_refundUser.balance, 0);
|
|
1257
1252
|
// The user should have have a token
|
|
1258
1253
|
assertEq(_hook.balanceOf(_refundUser), 1);
|
|
1259
|
-
uint256 _numberBurned = _hook.store().numberOfBurnedFor(address(_hook), _tierId);
|
|
1260
1254
|
// Craft the metadata: redeem the tokenId
|
|
1261
1255
|
bytes memory cashOutMetadata;
|
|
1262
1256
|
{
|
|
@@ -1305,7 +1299,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1305
1299
|
return (_tierId * 1_000_000_000) + _tokenNumber;
|
|
1306
1300
|
}
|
|
1307
1301
|
|
|
1308
|
-
function _buildPayMetadata(bytes memory metadata) internal returns (bytes memory) {
|
|
1302
|
+
function _buildPayMetadata(bytes memory metadata) internal view returns (bytes memory) {
|
|
1309
1303
|
// Build the metadata using the tiers to mint and the overspending flag.
|
|
1310
1304
|
bytes[] memory data = new bytes[](1);
|
|
1311
1305
|
data[0] = metadata;
|
|
@@ -1318,7 +1312,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1318
1312
|
return metadataHelper().createMetadata(ids, data);
|
|
1319
1313
|
}
|
|
1320
1314
|
|
|
1321
|
-
function _buildCashOutMetadata(bytes memory metadata) internal returns (bytes memory) {
|
|
1315
|
+
function _buildCashOutMetadata(bytes memory metadata) internal view returns (bytes memory) {
|
|
1322
1316
|
// Build the metadata using the tiers to mint and the overspending flag.
|
|
1323
1317
|
bytes[] memory data = new bytes[](1);
|
|
1324
1318
|
data[0] = metadata;
|
|
@@ -30,18 +30,18 @@ import {DefifaTierParams} from "../src/structs/DefifaTierParams.sol";
|
|
|
30
30
|
import {DefifaTierCashOutWeight} from "../src/structs/DefifaTierCashOutWeight.sol";
|
|
31
31
|
|
|
32
32
|
/// @dev Helper to read block.timestamp via an external call, bypassing the via-ir optimizer's timestamp caching.
|
|
33
|
-
contract
|
|
33
|
+
contract TimestampReaderRegressions {
|
|
34
34
|
function timestamp() external view returns (uint256) {
|
|
35
35
|
return block.timestamp;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/// @title
|
|
39
|
+
/// @title DefifaHookRegressions
|
|
40
40
|
/// @notice Regression tests for audit findings in DefifaHook.
|
|
41
|
-
contract
|
|
41
|
+
contract DefifaHookRegressions is JBTest, TestBaseWorkflow {
|
|
42
42
|
using JBRulesetMetadataResolver for JBRuleset;
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
TimestampReaderRegressions private _tsReader = new TimestampReaderRegressions();
|
|
45
45
|
|
|
46
46
|
address _protocolFeeProjectTokenAccount;
|
|
47
47
|
address _defifaProjectTokenAccount;
|
|
@@ -364,7 +364,7 @@ contract DefifaHook_AuditFindings is JBTest, TestBaseWorkflow {
|
|
|
364
364
|
return (_tierId * 1_000_000_000) + _tokenNumber;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
function _buildPayMetadata(bytes memory metadata) internal returns (bytes memory) {
|
|
367
|
+
function _buildPayMetadata(bytes memory metadata) internal view returns (bytes memory) {
|
|
368
368
|
bytes[] memory data = new bytes[](1);
|
|
369
369
|
data[0] = metadata;
|
|
370
370
|
bytes4[] memory ids = new bytes4[](1);
|
|
@@ -892,7 +892,7 @@ contract DefifaNoContestTest is JBTest, TestBaseWorkflow {
|
|
|
892
892
|
});
|
|
893
893
|
}
|
|
894
894
|
|
|
895
|
-
function _cashOutMeta(uint256 tid, uint256 tnum) internal returns (bytes memory) {
|
|
895
|
+
function _cashOutMeta(uint256 tid, uint256 tnum) internal view returns (bytes memory) {
|
|
896
896
|
uint256[] memory cid = new uint256[](1);
|
|
897
897
|
cid[0] = (tid * 1_000_000_000) + tnum;
|
|
898
898
|
bytes[] memory data = new bytes[](1);
|
|
@@ -678,7 +678,7 @@ contract DefifaSecurityTest is JBTest, TestBaseWorkflow {
|
|
|
678
678
|
});
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
-
function _cashOutMeta(uint256 tid, uint256 tnum) internal returns (bytes memory) {
|
|
681
|
+
function _cashOutMeta(uint256 tid, uint256 tnum) internal view returns (bytes memory) {
|
|
682
682
|
uint256[] memory cid = new uint256[](1);
|
|
683
683
|
cid[0] = (tid * 1_000_000_000) + tnum;
|
|
684
684
|
bytes[] memory data = new bytes[](1);
|