@ballkidz/defifa 0.0.5 → 0.0.7
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 +148 -44
- package/foundry.toml +0 -3
- package/package.json +8 -6
- package/remappings.txt +0 -5
- package/script/Deploy.s.sol +14 -12
- package/script/helpers/DefifaDeploymentLib.sol +26 -8
- package/src/DefifaDeployer.sol +15 -6
- package/src/DefifaGovernor.sol +5 -5
- package/src/DefifaHook.sol +22 -16
- package/src/DefifaTokenUriResolver.sol +3 -2
- package/src/interfaces/IDefifaDeployer.sol +0 -1
- package/src/interfaces/IDefifaGovernor.sol +0 -1
- package/src/interfaces/IDefifaTokenUriResolver.sol +0 -2
- package/src/libraries/DefifaHookLib.sol +5 -3
- package/src/structs/DefifaLaunchProjectData.sol +0 -2
- package/test/DefifaFeeAccounting.t.sol +4 -4
- package/test/DefifaGovernor.t.sol +4 -10
- 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` (stack depth). 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
|
|
@@ -270,9 +253,12 @@ uint256 public constant MAX_RESERVED_PERCENT = 10_000;
|
|
|
270
253
|
|
|
271
254
|
## Function Calls
|
|
272
255
|
|
|
273
|
-
Use named
|
|
256
|
+
Use named arguments for all function calls with 2 or more arguments — in both `src/` and `script/`:
|
|
274
257
|
|
|
275
258
|
```solidity
|
|
259
|
+
// Good — named arguments
|
|
260
|
+
token.mint({account: beneficiary, amount: count});
|
|
261
|
+
_transferOwnership({newOwner: address(0), projectId: 0});
|
|
276
262
|
PERMISSIONS.hasPermission({
|
|
277
263
|
operator: sender,
|
|
278
264
|
account: account,
|
|
@@ -281,8 +267,18 @@ PERMISSIONS.hasPermission({
|
|
|
281
267
|
includeRoot: true,
|
|
282
268
|
includeWildcardProjectId: true
|
|
283
269
|
});
|
|
270
|
+
|
|
271
|
+
// Bad — positional arguments with 2+ args
|
|
272
|
+
token.mint(beneficiary, count);
|
|
273
|
+
_transferOwnership(address(0), 0);
|
|
284
274
|
```
|
|
285
275
|
|
|
276
|
+
Single-argument calls use positional style: `_burn(amount)`.
|
|
277
|
+
|
|
278
|
+
This also applies to constructor calls, struct literals, and inherited/library calls (e.g., OZ `_mint`, `_safeMint`, `safeTransfer`, `allowance`, `Clones.cloneDeterministic`).
|
|
279
|
+
|
|
280
|
+
Named argument keys must use **camelCase** — never underscores. If a function's parameter names use underscores, rename them to camelCase first.
|
|
281
|
+
|
|
286
282
|
## Multiline Signatures
|
|
287
283
|
|
|
288
284
|
```solidity
|
|
@@ -326,7 +322,7 @@ try hook.afterPayRecordedWith(context) {} catch (bytes memory reason) {
|
|
|
326
322
|
|
|
327
323
|
### foundry.toml
|
|
328
324
|
|
|
329
|
-
Standard config
|
|
325
|
+
Standard config across all repos:
|
|
330
326
|
|
|
331
327
|
```toml
|
|
332
328
|
[profile.default]
|
|
@@ -336,9 +332,6 @@ optimizer_runs = 200
|
|
|
336
332
|
libs = ["node_modules", "lib"]
|
|
337
333
|
fs_permissions = [{ access = "read-write", path = "./"}]
|
|
338
334
|
|
|
339
|
-
[profile.ci_sizes]
|
|
340
|
-
optimizer_runs = 200
|
|
341
|
-
|
|
342
335
|
[fuzz]
|
|
343
336
|
runs = 4096
|
|
344
337
|
|
|
@@ -353,7 +346,14 @@ multiline_func_header = "all"
|
|
|
353
346
|
wrap_comments = true
|
|
354
347
|
```
|
|
355
348
|
|
|
356
|
-
|
|
349
|
+
**Optional sections (add only when needed):**
|
|
350
|
+
- `[rpc_endpoints]` — repos with fork tests. Maps named endpoints to env vars (e.g. `ethereum = "${RPC_ETHEREUM_MAINNET}"`).
|
|
351
|
+
- `[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).
|
|
352
|
+
|
|
353
|
+
**Common variations:**
|
|
354
|
+
- `via_ir = true` when hitting stack-too-deep
|
|
355
|
+
- `optimizer = false` when optimization causes stack-too-deep
|
|
356
|
+
- `optimizer_runs` reduced when deep struct nesting causes stack-too-deep at 200 runs
|
|
357
357
|
|
|
358
358
|
### CI Workflows
|
|
359
359
|
|
|
@@ -383,8 +383,10 @@ jobs:
|
|
|
383
383
|
uses: foundry-rs/foundry-toolchain@v1
|
|
384
384
|
- name: Run tests
|
|
385
385
|
run: forge test --fail-fast --summary --detailed --skip "*/script/**"
|
|
386
|
+
env:
|
|
387
|
+
RPC_ETHEREUM_MAINNET: ${{ secrets.RPC_ETHEREUM_MAINNET }}
|
|
386
388
|
- name: Check contract sizes
|
|
387
|
-
run:
|
|
389
|
+
run: forge build --sizes --skip "*/test/**" --skip "*/script/**" --skip SphinxUtils
|
|
388
390
|
```
|
|
389
391
|
|
|
390
392
|
**lint.yml:**
|
|
@@ -406,14 +408,63 @@ jobs:
|
|
|
406
408
|
run: forge fmt --check
|
|
407
409
|
```
|
|
408
410
|
|
|
411
|
+
**slither.yml** (repos with `src/` contracts only):
|
|
412
|
+
```yaml
|
|
413
|
+
name: slither
|
|
414
|
+
on:
|
|
415
|
+
pull_request:
|
|
416
|
+
branches:
|
|
417
|
+
- main
|
|
418
|
+
push:
|
|
419
|
+
branches:
|
|
420
|
+
- main
|
|
421
|
+
jobs:
|
|
422
|
+
analyze:
|
|
423
|
+
runs-on: ubuntu-latest
|
|
424
|
+
steps:
|
|
425
|
+
- uses: actions/checkout@v4
|
|
426
|
+
with:
|
|
427
|
+
submodules: recursive
|
|
428
|
+
- uses: actions/setup-node@v4
|
|
429
|
+
with:
|
|
430
|
+
node-version: latest
|
|
431
|
+
- name: Install npm dependencies
|
|
432
|
+
run: npm install --omit=dev
|
|
433
|
+
- name: Install Foundry
|
|
434
|
+
uses: foundry-rs/foundry-toolchain@v1
|
|
435
|
+
- name: Run slither
|
|
436
|
+
uses: crytic/slither-action@v0.3.1
|
|
437
|
+
with:
|
|
438
|
+
slither-config: slither-ci.config.json
|
|
439
|
+
fail-on: medium
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
**slither-ci.config.json:**
|
|
443
|
+
```json
|
|
444
|
+
{
|
|
445
|
+
"detectors_to_exclude": "timestamp,uninitialized-local,naming-convention,solc-version,shadowing-local",
|
|
446
|
+
"exclude_informational": true,
|
|
447
|
+
"exclude_low": false,
|
|
448
|
+
"exclude_medium": false,
|
|
449
|
+
"exclude_high": false,
|
|
450
|
+
"disable_color": false,
|
|
451
|
+
"filter_paths": "(mocks/|test/|node_modules/|lib/)",
|
|
452
|
+
"legacy_ast": false
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**Variations:**
|
|
457
|
+
- 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.
|
|
458
|
+
- 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.
|
|
459
|
+
|
|
409
460
|
### package.json
|
|
410
461
|
|
|
411
462
|
```json
|
|
412
463
|
{
|
|
413
|
-
"name": "@bananapus/
|
|
464
|
+
"name": "@bananapus/package-name-v6",
|
|
414
465
|
"version": "x.x.x",
|
|
415
466
|
"license": "MIT",
|
|
416
|
-
"repository": { "type": "git", "url": "git+https://github.com/
|
|
467
|
+
"repository": { "type": "git", "url": "git+https://github.com/Org/repo.git" },
|
|
417
468
|
"engines": { "node": ">=20.0.0" },
|
|
418
469
|
"scripts": {
|
|
419
470
|
"test": "forge test",
|
|
@@ -430,13 +481,62 @@ jobs:
|
|
|
430
481
|
|
|
431
482
|
### remappings.txt
|
|
432
483
|
|
|
433
|
-
Every repo has a `remappings.txt
|
|
484
|
+
Every repo has a `remappings.txt` as the **single source of truth** for import remappings. Never add remappings to `foundry.toml`.
|
|
485
|
+
|
|
486
|
+
**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.
|
|
487
|
+
|
|
488
|
+
**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.
|
|
489
|
+
|
|
490
|
+
**Minimal content** (most repos):
|
|
491
|
+
|
|
492
|
+
```
|
|
493
|
+
forge-std/=lib/forge-std/src/
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Only add extra remappings for:
|
|
497
|
+
- **`forge-std`** — always needed (git submodule with `src/` subdirectory)
|
|
498
|
+
- **Repo-specific `lib/` submodules** that have no npm package (e.g., `hookmate/=lib/hookmate/src/`)
|
|
499
|
+
- **Symlinked npm packages** — need explicit `@scope/package/=node_modules/@scope/package/` entries
|
|
500
|
+
- **Nested transitive deps** — e.g., `@chainlink/contracts-ccip/` nested inside `@bananapus/suckers-v6/node_modules/`
|
|
434
501
|
|
|
502
|
+
**Never add remappings for:**
|
|
503
|
+
- npm packages that match their import path and are installed as real directories — they auto-resolve
|
|
504
|
+
- Short-form aliases (e.g., `@bananapus/core/` → `@bananapus/core-v6/src/`) — fix the import instead
|
|
505
|
+
- Packages available via npm that are also git submodules — remove the submodule, use npm
|
|
506
|
+
|
|
507
|
+
**Import path convention:**
|
|
508
|
+
|
|
509
|
+
| Package | Import path | Resolves to |
|
|
510
|
+
|---------|------------|-------------|
|
|
511
|
+
| `@bananapus/core-v6` | `@bananapus/core-v6/src/libraries/JBConstants.sol` | `node_modules/@bananapus/core-v6/src/...` |
|
|
512
|
+
| `@openzeppelin/contracts` | `@openzeppelin/contracts/token/ERC20/IERC20.sol` | `node_modules/@openzeppelin/contracts/...` |
|
|
513
|
+
| `@uniswap/v4-core` | `@uniswap/v4-core/src/interfaces/IPoolManager.sol` | `node_modules/@uniswap/v4-core/src/...` |
|
|
514
|
+
|
|
515
|
+
### Linting
|
|
516
|
+
|
|
517
|
+
Solar (Foundry's built-in linter) runs automatically during `forge build`. It scans all `.sol` files in `libs` directories, including `node_modules`.
|
|
518
|
+
|
|
519
|
+
**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.
|
|
520
|
+
|
|
521
|
+
### Fork Tests
|
|
522
|
+
|
|
523
|
+
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.
|
|
524
|
+
|
|
525
|
+
```solidity
|
|
526
|
+
function setUp() public {
|
|
527
|
+
vm.createSelectFork("ethereum");
|
|
528
|
+
// ... setup code
|
|
529
|
+
}
|
|
435
530
|
```
|
|
436
|
-
|
|
531
|
+
|
|
532
|
+
The endpoint name (e.g. `"ethereum"`) maps to an env var via `foundry.toml`:
|
|
533
|
+
|
|
534
|
+
```toml
|
|
535
|
+
[rpc_endpoints]
|
|
536
|
+
ethereum = "${RPC_ETHEREUM_MAINNET}"
|
|
437
537
|
```
|
|
438
538
|
|
|
439
|
-
|
|
539
|
+
For multi-chain fork tests, add all needed endpoints.
|
|
440
540
|
|
|
441
541
|
### Formatting
|
|
442
542
|
|
|
@@ -464,4 +564,8 @@ CI checks formatting via `forge fmt --check`.
|
|
|
464
564
|
|
|
465
565
|
### Contract Size Checks
|
|
466
566
|
|
|
467
|
-
CI runs `
|
|
567
|
+
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`.
|
|
568
|
+
|
|
569
|
+
## Repo-Specific Deviations
|
|
570
|
+
|
|
571
|
+
None. This repo follows the standard configuration exactly.
|
package/foundry.toml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ballkidz/defifa",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0"
|
|
@@ -13,12 +13,14 @@
|
|
|
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
|
-
"@
|
|
16
|
+
"@bananapus/721-hook-v6": "^0.0.16",
|
|
17
|
+
"@bananapus/address-registry-v6": "^0.0.9",
|
|
18
|
+
"@bananapus/core-v6": "^0.0.16",
|
|
19
|
+
"@bananapus/permission-ids-v6": "^0.0.9",
|
|
20
|
+
"@croptop/core-v6": "^0.0.15",
|
|
21
|
+
"@openzeppelin/contracts": "^5.6.1",
|
|
21
22
|
"@prb/math": "^4.1.1",
|
|
23
|
+
"@rev-net/core-v6": "^0.0.12",
|
|
22
24
|
"scripty.sol": "^2.1.1"
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
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 {
|
|
@@ -91,18 +91,20 @@ contract DeployMainnet is Script, Sphinx {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
function deploy() public sphinx {
|
|
94
|
-
DefifaHook hook = new DefifaHook{salt: _salt}(
|
|
94
|
+
DefifaHook hook = new DefifaHook{salt: _salt}({
|
|
95
|
+
_directory: core.directory, _defifaToken: defifaToken, _baseProtocolToken: baseProtocolToken
|
|
96
|
+
});
|
|
95
97
|
DefifaTokenUriResolver tokenUriResolver = new DefifaTokenUriResolver{salt: _salt}(_typeface);
|
|
96
|
-
DefifaGovernor governor = new DefifaGovernor{salt: _salt}(core.controller, safeAddress());
|
|
97
|
-
DefifaDeployer deployer = new DefifaDeployer{salt: _salt}(
|
|
98
|
-
address(hook),
|
|
99
|
-
tokenUriResolver,
|
|
100
|
-
governor,
|
|
101
|
-
core.controller,
|
|
102
|
-
registry.registry,
|
|
103
|
-
_defifaProjectId,
|
|
104
|
-
_baseProtocolProjectId
|
|
105
|
-
);
|
|
98
|
+
DefifaGovernor governor = new DefifaGovernor{salt: _salt}({_controller: core.controller, _owner: safeAddress()});
|
|
99
|
+
DefifaDeployer deployer = new DefifaDeployer{salt: _salt}({
|
|
100
|
+
_hookCodeOrigin: address(hook),
|
|
101
|
+
_tokenUriResolver: tokenUriResolver,
|
|
102
|
+
_governor: governor,
|
|
103
|
+
_controller: core.controller,
|
|
104
|
+
_registry: registry.registry,
|
|
105
|
+
_defifaProjectId: _defifaProjectId,
|
|
106
|
+
_baseProtocolProjectId: _baseProtocolProjectId
|
|
107
|
+
});
|
|
106
108
|
|
|
107
109
|
governor.transferOwnership(address(deployer));
|
|
108
110
|
}
|
|
@@ -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;
|
|
@@ -34,7 +34,7 @@ library DefifaDeploymentLib {
|
|
|
34
34
|
|
|
35
35
|
for (uint256 _i; _i < networks.length; _i++) {
|
|
36
36
|
if (networks[_i].chainId == chainId) {
|
|
37
|
-
return getDeployment(path, networks[_i].name);
|
|
37
|
+
return getDeployment({path: path, network_name: networks[_i].name});
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -49,14 +49,32 @@ library DefifaDeploymentLib {
|
|
|
49
49
|
view
|
|
50
50
|
returns (DefifaDeployment memory deployment)
|
|
51
51
|
{
|
|
52
|
-
deployment.hook = DefifaHook(
|
|
52
|
+
deployment.hook = DefifaHook(
|
|
53
|
+
_getDeploymentAddress({
|
|
54
|
+
path: path, project_name: PROJECT_NAME, network_name: network_name, contractName: "DefifaHook"
|
|
55
|
+
})
|
|
56
|
+
);
|
|
53
57
|
|
|
54
|
-
deployment.deployer = DefifaDeployer(
|
|
58
|
+
deployment.deployer = DefifaDeployer(
|
|
59
|
+
_getDeploymentAddress({
|
|
60
|
+
path: path, project_name: PROJECT_NAME, network_name: network_name, contractName: "DefifaDeployer"
|
|
61
|
+
})
|
|
62
|
+
);
|
|
55
63
|
|
|
56
|
-
deployment.governor = DefifaGovernor(
|
|
64
|
+
deployment.governor = DefifaGovernor(
|
|
65
|
+
_getDeploymentAddress({
|
|
66
|
+
path: path, project_name: PROJECT_NAME, network_name: network_name, contractName: "DefifaGovernor"
|
|
67
|
+
})
|
|
68
|
+
);
|
|
57
69
|
|
|
58
|
-
deployment.tokenUriResolver =
|
|
59
|
-
|
|
70
|
+
deployment.tokenUriResolver = DefifaTokenUriResolver(
|
|
71
|
+
_getDeploymentAddress({
|
|
72
|
+
path: path,
|
|
73
|
+
project_name: PROJECT_NAME,
|
|
74
|
+
network_name: network_name,
|
|
75
|
+
contractName: "DefifaTokenUriResolver"
|
|
76
|
+
})
|
|
77
|
+
);
|
|
60
78
|
}
|
|
61
79
|
|
|
62
80
|
/// @notice Get the address of a contract that was deployed by the Deploy script.
|
|
@@ -78,6 +96,6 @@ library DefifaDeploymentLib {
|
|
|
78
96
|
{
|
|
79
97
|
string memory deploymentJson =
|
|
80
98
|
vm.readFile(string.concat(path, project_name, "/", network_name, "/", contractName, ".json"));
|
|
81
|
-
return stdJson.readAddress(deploymentJson, ".address");
|
|
99
|
+
return stdJson.readAddress({json: deploymentJson, key: ".address"});
|
|
82
100
|
}
|
|
83
101
|
}
|
package/src/DefifaDeployer.sol
CHANGED
|
@@ -323,7 +323,8 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
323
323
|
if (_pot == 0) revert DefifaDeployer_NothingToFulfill();
|
|
324
324
|
|
|
325
325
|
// Compute the fee amount based on the total absolute split percent stored at game creation.
|
|
326
|
-
uint256 _feeAmount =
|
|
326
|
+
uint256 _feeAmount =
|
|
327
|
+
mulDiv({x: _pot, y: _commitmentPercentOf[gameId], denominator: JBConstants.SPLITS_TOTAL_PERCENT});
|
|
327
328
|
|
|
328
329
|
// Store the actual fee amount for accurate currentGamePotOf reporting.
|
|
329
330
|
// Use max(feeAmount, 1) to preserve the reentrancy guard when pot is 0.
|
|
@@ -523,7 +524,9 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
523
524
|
// cloneDeterministic with msg.sender in the salt prevents this since a different
|
|
524
525
|
// caller produces a different address.
|
|
525
526
|
DefifaHook _hook = DefifaHook(
|
|
526
|
-
Clones.cloneDeterministic(
|
|
527
|
+
Clones.cloneDeterministic({
|
|
528
|
+
implementation: hookCodeOrigin, salt: keccak256(abi.encodePacked(msg.sender, _currentNonce))
|
|
529
|
+
})
|
|
527
530
|
);
|
|
528
531
|
|
|
529
532
|
// Use the default uri resolver if provided, else use the hardcoded generic default.
|
|
@@ -857,14 +860,20 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
857
860
|
uint256 _normalizedTotal;
|
|
858
861
|
for (uint256 _i; _i < _numberOfUserSplits; _i++) {
|
|
859
862
|
_splits[_i] = _initialSplits[_i];
|
|
860
|
-
_splits[_i].percent =
|
|
861
|
-
|
|
863
|
+
_splits[_i].percent = uint32(
|
|
864
|
+
mulDiv({
|
|
865
|
+
x: _initialSplits[_i].percent,
|
|
866
|
+
y: JBConstants.SPLITS_TOTAL_PERCENT,
|
|
867
|
+
denominator: _totalAbsolutePercent
|
|
868
|
+
})
|
|
869
|
+
);
|
|
862
870
|
_normalizedTotal += _splits[_i].percent;
|
|
863
871
|
}
|
|
864
872
|
|
|
865
873
|
// Add Defifa fee split (normalized).
|
|
866
|
-
uint256 _defifaNormalized =
|
|
867
|
-
|
|
874
|
+
uint256 _defifaNormalized = mulDiv({
|
|
875
|
+
x: _defifaAbsolutePercent, y: JBConstants.SPLITS_TOTAL_PERCENT, denominator: _totalAbsolutePercent
|
|
876
|
+
});
|
|
868
877
|
_splits[_numberOfUserSplits] = JBSplit({
|
|
869
878
|
preferAddToBalance: false,
|
|
870
879
|
percent: uint32(_defifaNormalized),
|
package/src/DefifaGovernor.sol
CHANGED
|
@@ -182,12 +182,12 @@ contract DefifaGovernor is Ownable, IDefifaGovernor {
|
|
|
182
182
|
// e.g. holding 3 of 10 tokens → 3/10 * MAX_ATTESTATION_POWER_TIER attestation power from this tier.
|
|
183
183
|
unchecked {
|
|
184
184
|
if (_tierAttestationUnitsForAccount != 0) {
|
|
185
|
-
attestationPower += mulDiv(
|
|
186
|
-
MAX_ATTESTATION_POWER_TIER,
|
|
187
|
-
_tierAttestationUnitsForAccount,
|
|
188
|
-
IDefifaHook(_metadata.dataHook)
|
|
185
|
+
attestationPower += mulDiv({
|
|
186
|
+
x: MAX_ATTESTATION_POWER_TIER,
|
|
187
|
+
y: _tierAttestationUnitsForAccount,
|
|
188
|
+
denominator: IDefifaHook(_metadata.dataHook)
|
|
189
189
|
.getPastTierTotalAttestationUnitsOf({tier: _tierId, timestamp: _timestamp})
|
|
190
|
-
);
|
|
190
|
+
});
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
}
|