@ballkidz/defifa 0.0.29 → 0.0.31
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/ARCHITECTURE.md +2 -2
- package/CHANGELOG.md +2 -2
- package/CRYPTO_ECON.md +1 -1
- package/README.md +3 -3
- package/RISKS.md +1 -1
- package/SKILLS.md +1 -1
- package/STYLE_GUIDE.md +2 -50
- package/package.json +3 -3
- package/src/DefifaDeployer.sol +62 -50
- package/src/DefifaGovernor.sol +74 -63
- package/src/DefifaHook.sol +130 -184
- package/src/DefifaProjectOwner.sol +4 -2
- package/src/DefifaTokenUriResolver.sol +15 -13
- package/src/interfaces/IDefifaDeployer.sol +0 -16
- package/src/interfaces/IDefifaHook.sol +0 -4
- package/src/libraries/DefifaHookLib.sol +261 -151
package/ARCHITECTURE.md
CHANGED
|
@@ -115,7 +115,7 @@ The hook's completion math is intentionally phase-sensitive:
|
|
|
115
115
|
- fulfillment and ratification coupling:
|
|
116
116
|
`test/regression/FulfillmentBlocksRatification.t.sol`
|
|
117
117
|
- pending reserve effects on completion fairness:
|
|
118
|
-
`test/
|
|
118
|
+
`test/regression/PendingReserveSnapshotBypass.t.sol`
|
|
119
119
|
|
|
120
120
|
## Source Map
|
|
121
121
|
|
|
@@ -128,4 +128,4 @@ The hook's completion math is intentionally phase-sensitive:
|
|
|
128
128
|
- `test/DefifaHookRegressions.t.sol`
|
|
129
129
|
- `test/DefifaFeeAccounting.t.sol`
|
|
130
130
|
- `test/regression/FulfillmentBlocksRatification.t.sol`
|
|
131
|
-
- `test/
|
|
131
|
+
- `test/regression/PendingReserveSnapshotBypass.t.sol`
|
package/CHANGELOG.md
CHANGED
|
@@ -17,10 +17,10 @@ This file instead describes the current v6 repo at a high level and the broad mi
|
|
|
17
17
|
## Summary
|
|
18
18
|
|
|
19
19
|
- The repo is now built directly on the v6 Juicebox stack, including the v6 core and 721-hook packages.
|
|
20
|
-
- The v6 surface is split across dedicated deployer, hook, governor, project-owner, and token-uri contracts, with dedicated regression and
|
|
20
|
+
- The v6 surface is split across dedicated deployer, hook, governor, project-owner, and token-uri contracts, with dedicated regression and review test coverage around governance, fee accounting, attestations, and lifecycle edge cases.
|
|
21
21
|
- Solidity and tooling were upgraded to the v6 baseline around `0.8.28`.
|
|
22
22
|
|
|
23
|
-
## Local
|
|
23
|
+
## Local review remediations
|
|
24
24
|
|
|
25
25
|
- Reserve-minted NFTs are now excluded from refund calculations during MINT, REFUND, and NO_CONTEST phases. A public `isReserveMint` mapping tracks which tokens were created via tier reserve frequency rather than paid for. `beforeCashOutRecordedWith` subtracts their tier price from `cumulativeMintPrice`, preventing reserve beneficiaries from withdrawing funds they never contributed.
|
|
26
26
|
|
package/CRYPTO_ECON.md
CHANGED
|
@@ -1187,4 +1187,4 @@ Defifa implements a rigorous approach to prediction gaming through the compositi
|
|
|
1187
1187
|
|
|
1188
1188
|
The elegance of Defifa resides in its architectural composability: prediction games with arbitrary outcomes, arbitrary tier structures, and arbitrary payout distributions emerge from the same set of twelve parameters (Eq. 1), executed deterministically by immutable smart contracts with a single, time-bounded governance input. From a 4-team presidential election to a 32-team World Cup, the same protocol handles it all — and the safety mechanisms ensure that every game resolves, one way or another.
|
|
1189
1189
|
|
|
1190
|
-
The most significant
|
|
1190
|
+
The most significant result is the Uniform Participation Theorem: **a game with uniform tier supply is provably impervious to profitable governance attacks regardless of attacker capital.** This transforms game design from an art into an engineering discipline — the designer's job is to choose events and tier structures that naturally produce uniform participation, and the cryptoeconomics handle the rest.
|
package/README.md
CHANGED
|
@@ -117,7 +117,7 @@ src/
|
|
|
117
117
|
libraries/
|
|
118
118
|
structs/
|
|
119
119
|
test/
|
|
120
|
-
governance, fee-accounting, no-contest, adversarial, regression, fork, and
|
|
120
|
+
governance, fee-accounting, no-contest, adversarial, regression, fork, and review coverage
|
|
121
121
|
script/
|
|
122
122
|
Deploy.s.sol
|
|
123
123
|
helpers/
|
|
@@ -141,8 +141,8 @@ references/
|
|
|
141
141
|
- [`test/DefifaFeeAccounting.t.sol`](./test/DefifaFeeAccounting.t.sol)
|
|
142
142
|
- [`test/DefifaNoContest.t.sol`](./test/DefifaNoContest.t.sol)
|
|
143
143
|
- [`test/DefifaAdversarialQuorum.t.sol`](./test/DefifaAdversarialQuorum.t.sol)
|
|
144
|
-
- [`test/
|
|
145
|
-
- [`test/
|
|
144
|
+
- [`test/regression/PendingReserveDilution.t.sol`](./test/regression/PendingReserveDilution.t.sol)
|
|
145
|
+
- [`test/regression/AttestationDoubleCount.t.sol`](./test/regression/AttestationDoubleCount.t.sol)
|
|
146
146
|
- [`test/regression/GracePeriodBypass.t.sol`](./test/regression/GracePeriodBypass.t.sol)
|
|
147
147
|
|
|
148
148
|
## Deployment Notes
|
package/RISKS.md
CHANGED
|
@@ -6,7 +6,7 @@ This file focuses on the game-theoretic, governance, and settlement risks in Def
|
|
|
6
6
|
|
|
7
7
|
- Read `Priority risks` first.
|
|
8
8
|
- Use the detailed sections below to reason about governor power, live supply assumptions, and downstream hook dependencies.
|
|
9
|
-
- Treat `Accepted Behaviors` and `Invariants to Verify` as explicit boundaries for
|
|
9
|
+
- Treat `Accepted Behaviors` and `Invariants to Verify` as explicit boundaries for review scope.
|
|
10
10
|
|
|
11
11
|
## Priority risks
|
|
12
12
|
|
package/SKILLS.md
CHANGED
|
@@ -43,4 +43,4 @@ Defifa is an onchain prediction game system built on Juicebox. This repo package
|
|
|
43
43
|
- Defifa-specific cash-out weights and governance thresholds sit on top of `nana-721-hook-v6` and `nana-core-v6`.
|
|
44
44
|
- When a task mentions NFT rendering or metadata, confirm whether it belongs in [`src/DefifaTokenUriResolver.sol`](./src/DefifaTokenUriResolver.sol).
|
|
45
45
|
- If you edit phase transitions, check lifecycle, governance, and fee-accounting tests together.
|
|
46
|
-
- If ratification, attestation, or quorum behavior changes, re-read the
|
|
46
|
+
- If ratification, attestation, or quorum behavior changes, re-read the review and regression tests before trusting a clean happy-path result.
|
package/STYLE_GUIDE.md
CHANGED
|
@@ -451,57 +451,9 @@ jobs:
|
|
|
451
451
|
run: forge fmt --check
|
|
452
452
|
```
|
|
453
453
|
|
|
454
|
-
**
|
|
455
|
-
```yaml
|
|
456
|
-
name: slither
|
|
457
|
-
on:
|
|
458
|
-
pull_request:
|
|
459
|
-
branches:
|
|
460
|
-
- main
|
|
461
|
-
push:
|
|
462
|
-
branches:
|
|
463
|
-
- main
|
|
464
|
-
jobs:
|
|
465
|
-
analyze:
|
|
466
|
-
runs-on: ubuntu-latest
|
|
467
|
-
steps:
|
|
468
|
-
- uses: actions/checkout@v4
|
|
469
|
-
with:
|
|
470
|
-
submodules: recursive
|
|
471
|
-
- uses: actions/setup-node@v4
|
|
472
|
-
with:
|
|
473
|
-
node-version: 25.9.0
|
|
474
|
-
- name: Install npm dependencies
|
|
475
|
-
run: npm install --omit=dev
|
|
476
|
-
- name: Install Foundry
|
|
477
|
-
uses: foundry-rs/foundry-toolchain@v1
|
|
478
|
-
- name: Prebuild contracts
|
|
479
|
-
run: forge build --deny notes --build-info --skip "*/test/**" --skip "*/script/**"
|
|
480
|
-
- name: Run slither
|
|
481
|
-
uses: crytic/slither-action@v0.4.1
|
|
482
|
-
with:
|
|
483
|
-
slither-config: slither-ci.config.json
|
|
484
|
-
fail-on: medium
|
|
485
|
-
ignore-compile: true
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
**slither-ci.config.json:**
|
|
489
|
-
```json
|
|
490
|
-
{
|
|
491
|
-
"detectors_to_exclude": "timestamp,uninitialized-local,naming-convention,solc-version,shadowing-local",
|
|
492
|
-
"exclude_informational": true,
|
|
493
|
-
"exclude_low": false,
|
|
494
|
-
"exclude_medium": false,
|
|
495
|
-
"exclude_high": false,
|
|
496
|
-
"disable_color": false,
|
|
497
|
-
"filter_paths": "(mocks/|test/|node_modules/|lib/)",
|
|
498
|
-
"legacy_ast": false
|
|
499
|
-
}
|
|
500
|
-
```
|
|
454
|
+
**Static review workflow** (repos with `src/` contracts only):
|
|
501
455
|
|
|
502
|
-
|
|
503
|
-
- 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.
|
|
504
|
-
- 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.
|
|
456
|
+
Keep repo-local static review automation current with the package's runtime surface. At minimum, CI should run formatting, linting, and build checks with `--deny notes`. Repos that only contain deployment scripts can rely on the shared formatting and lint jobs unless they add runtime contracts.
|
|
505
457
|
|
|
506
458
|
### package.json
|
|
507
459
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ballkidz/defifa",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.31",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "25.9.0"
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"remappings.txt"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@bananapus/721-hook-v6": "0.0.
|
|
34
|
+
"@bananapus/721-hook-v6": "0.0.46",
|
|
35
35
|
"@bananapus/address-registry-v6": "0.0.25",
|
|
36
|
-
"@bananapus/core-v6": "0.0.
|
|
36
|
+
"@bananapus/core-v6": "0.0.44",
|
|
37
37
|
"@bananapus/permission-ids-v6": "0.0.22",
|
|
38
38
|
"@openzeppelin/contracts": "5.6.1",
|
|
39
39
|
"@prb/math": "4.1.1",
|
package/src/DefifaDeployer.sol
CHANGED
|
@@ -54,18 +54,14 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
54
54
|
// --------------------------- custom errors ------------------------- //
|
|
55
55
|
//*********************************************************************//
|
|
56
56
|
|
|
57
|
-
error DefifaDeployer_CantFulfillYet();
|
|
58
|
-
error
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
error
|
|
62
|
-
error
|
|
63
|
-
error
|
|
64
|
-
error
|
|
65
|
-
error DefifaDeployer_TerminalNotFound();
|
|
66
|
-
error DefifaDeployer_PhaseAlreadyQueued();
|
|
67
|
-
error DefifaDeployer_SplitsDontAddUp();
|
|
68
|
-
error DefifaDeployer_UnexpectedTerminalCurrency();
|
|
57
|
+
error DefifaDeployer_CantFulfillYet(uint256 gameId);
|
|
58
|
+
error DefifaDeployer_InvalidGameConfiguration(
|
|
59
|
+
uint256 start, uint256 mintPeriodDuration, uint256 refundPeriodDuration, uint256 tierCount
|
|
60
|
+
);
|
|
61
|
+
error DefifaDeployer_InvalidCurrency(address token, uint256 currency);
|
|
62
|
+
error DefifaDeployer_NotNoContest(uint256 gameId, DefifaGamePhase phase);
|
|
63
|
+
error DefifaDeployer_NoContestAlreadyTriggered(uint256 gameId);
|
|
64
|
+
error DefifaDeployer_SplitsDontAddUp(uint256 totalPercent, uint256 maxPercent);
|
|
69
65
|
|
|
70
66
|
//*********************************************************************//
|
|
71
67
|
// ----------------------- internal properties ----------------------- //
|
|
@@ -182,7 +178,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
182
178
|
// Get the game's current funding cycle along with its metadata.
|
|
183
179
|
JBRuleset memory currentRuleset = CONTROLLER.RULESETS().currentOf(gameId);
|
|
184
180
|
// Get the game's queued funding cycle along with its metadata.
|
|
185
|
-
// slither-disable-next-line unused-return
|
|
186
181
|
(JBRuleset memory queuedRuleset,) = CONTROLLER.RULESETS().latestQueuedOf(gameId);
|
|
187
182
|
|
|
188
183
|
// If the configurations are the same and the game hasn't ended, queueing is still needed.
|
|
@@ -294,7 +289,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
294
289
|
uint256 _baseProtocolProjectId,
|
|
295
290
|
IJB721TiersHookStore _hookStore
|
|
296
291
|
) {
|
|
297
|
-
// slither-disable-next-line missing-zero-check
|
|
298
292
|
HOOK_CODE_ORIGIN = _hookCodeOrigin;
|
|
299
293
|
TOKEN_URI_RESOLVER = _tokenUriResolver;
|
|
300
294
|
GOVERNOR = _governor;
|
|
@@ -313,19 +307,17 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
313
307
|
|
|
314
308
|
/// @notice Fulfill split amounts between all splits for a game.
|
|
315
309
|
/// @param gameId The ID of the game to fulfill splits for.
|
|
316
|
-
// slither-disable-next-line reentrancy-benign,reentrancy-no-eth
|
|
317
310
|
function fulfillCommitmentsOf(uint256 gameId) external virtual override {
|
|
318
311
|
// Make sure commitments haven't already been fulfilled.
|
|
319
312
|
if (commitmentsFulfilledFor[gameId]) return;
|
|
320
313
|
commitmentsFulfilledFor[gameId] = true;
|
|
321
314
|
|
|
322
315
|
// Get the game's current funding cycle along with its metadata.
|
|
323
|
-
// slither-disable-next-line unused-return
|
|
324
316
|
(, JBRulesetMetadata memory metadata) = CONTROLLER.currentRulesetOf(gameId);
|
|
325
317
|
|
|
326
318
|
// Make sure the game's commitments can be fulfilled.
|
|
327
319
|
if (!IDefifaHook(metadata.dataHook).cashOutWeightIsSet()) {
|
|
328
|
-
revert DefifaDeployer_CantFulfillYet();
|
|
320
|
+
revert DefifaDeployer_CantFulfillYet({gameId: gameId});
|
|
329
321
|
}
|
|
330
322
|
|
|
331
323
|
// Get the game token and the terminal.
|
|
@@ -337,10 +329,8 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
337
329
|
uint256 pot = terminal.STORE().balanceOf({terminal: address(terminal), projectId: gameId, token: token});
|
|
338
330
|
|
|
339
331
|
// If the pot is empty, queue the final ruleset without attempting payouts.
|
|
340
|
-
// slither-disable-next-line incorrect-equality
|
|
341
332
|
if (pot == 0) {
|
|
342
333
|
_queueFinalRuleset({gameId: gameId, metadata: metadata});
|
|
343
|
-
// slither-disable-next-line reentrancy-events
|
|
344
334
|
emit FulfilledCommitments({gameId: gameId, pot: 0, caller: msg.sender});
|
|
345
335
|
return;
|
|
346
336
|
}
|
|
@@ -356,7 +346,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
356
346
|
// Use the ruleset's baseCurrency — this matches the currency under which payout limits were stored
|
|
357
347
|
// at launch time, regardless of whether the token is native ETH or an ERC-20.
|
|
358
348
|
// Wrapped in try-catch so the final ruleset is always queued even if payout fails.
|
|
359
|
-
// slither-disable-next-line unused-return,reentrancy-no-eth
|
|
360
349
|
try terminal.sendPayoutsOf({
|
|
361
350
|
projectId: gameId, token: token, amount: feeAmount, currency: metadata.baseCurrency, minTokensPaidOut: 0
|
|
362
351
|
}) {}
|
|
@@ -364,21 +353,18 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
364
353
|
// Payout failed — fee stays in pot. Reset to 0 so currentGamePotOf
|
|
365
354
|
// doesn't double-count the fee.
|
|
366
355
|
fulfilledCommitmentsOf[gameId] = 0;
|
|
367
|
-
// slither-disable-next-line reentrancy-events
|
|
368
356
|
emit CommitmentPayoutFailed({gameId: gameId, amount: feeAmount, reason: reason});
|
|
369
357
|
}
|
|
370
358
|
|
|
371
359
|
// Queue the final ruleset and emit.
|
|
372
360
|
_queueFinalRuleset({gameId: gameId, metadata: metadata});
|
|
373
361
|
|
|
374
|
-
// slither-disable-next-line reentrancy-events
|
|
375
362
|
emit FulfilledCommitments({gameId: gameId, pot: pot, caller: msg.sender});
|
|
376
363
|
}
|
|
377
364
|
|
|
378
365
|
/// @notice Launches a new game owned by this contract with a DefifaHook attached.
|
|
379
366
|
/// @param launchProjectData Data necessary to fulfill the transaction to launch a game.
|
|
380
367
|
/// @return gameId The ID of the newly configured game.
|
|
381
|
-
// slither-disable-next-line reentrancy-benign,reentrancy-no-eth
|
|
382
368
|
function launchGameWith(DefifaLaunchProjectData memory launchProjectData)
|
|
383
369
|
external
|
|
384
370
|
override
|
|
@@ -391,7 +377,14 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
391
377
|
if (launchProjectData.start == 0) {
|
|
392
378
|
uint256 start =
|
|
393
379
|
currentTimestamp + launchProjectData.mintPeriodDuration + launchProjectData.refundPeriodDuration;
|
|
394
|
-
if (start > type(uint48).max)
|
|
380
|
+
if (start > type(uint48).max) {
|
|
381
|
+
revert DefifaDeployer_InvalidGameConfiguration({
|
|
382
|
+
start: start,
|
|
383
|
+
mintPeriodDuration: launchProjectData.mintPeriodDuration,
|
|
384
|
+
refundPeriodDuration: launchProjectData.refundPeriodDuration,
|
|
385
|
+
tierCount: launchProjectData.tiers.length
|
|
386
|
+
});
|
|
387
|
+
}
|
|
395
388
|
|
|
396
389
|
// Casting to uint48 is safe because `start` was bounded above.
|
|
397
390
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
@@ -399,7 +392,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
399
392
|
}
|
|
400
393
|
// If callers provide a future start with no mint duration, derive a mint window that begins now and ends
|
|
401
394
|
// before the refund window. This preserves the requested start while keeping minting immediately available.
|
|
402
|
-
// slither-disable-next-line incorrect-equality
|
|
403
395
|
else if (
|
|
404
396
|
launchProjectData.mintPeriodDuration == 0
|
|
405
397
|
&& launchProjectData.start > currentTimestamp + launchProjectData.refundPeriodDuration
|
|
@@ -410,20 +402,34 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
410
402
|
|
|
411
403
|
// Make sure the provided gameplay timestamps are sequential and that there is a mint duration.
|
|
412
404
|
if (
|
|
413
|
-
// slither-disable-next-line incorrect-equality
|
|
414
405
|
launchProjectData.mintPeriodDuration == 0
|
|
415
406
|
|| launchProjectData.start
|
|
416
407
|
< currentTimestamp + launchProjectData.refundPeriodDuration + launchProjectData.mintPeriodDuration
|
|
417
|
-
)
|
|
408
|
+
) {
|
|
409
|
+
revert DefifaDeployer_InvalidGameConfiguration({
|
|
410
|
+
start: launchProjectData.start,
|
|
411
|
+
mintPeriodDuration: launchProjectData.mintPeriodDuration,
|
|
412
|
+
refundPeriodDuration: launchProjectData.refundPeriodDuration,
|
|
413
|
+
tierCount: launchProjectData.tiers.length
|
|
414
|
+
});
|
|
415
|
+
}
|
|
418
416
|
|
|
419
417
|
// The hook and governor hardcode uint256[128] tier-weight tables, so reject games with more than 128 tiers.
|
|
420
|
-
if (launchProjectData.tiers.length > 128)
|
|
418
|
+
if (launchProjectData.tiers.length > 128) {
|
|
419
|
+
revert DefifaDeployer_InvalidGameConfiguration({
|
|
420
|
+
start: launchProjectData.start,
|
|
421
|
+
mintPeriodDuration: launchProjectData.mintPeriodDuration,
|
|
422
|
+
refundPeriodDuration: launchProjectData.refundPeriodDuration,
|
|
423
|
+
tierCount: launchProjectData.tiers.length
|
|
424
|
+
});
|
|
425
|
+
}
|
|
421
426
|
|
|
422
427
|
// Reject ERC-20 games with a zero currency. A zero baseCurrency would cause payout limit lookups
|
|
423
428
|
// in fulfillCommitmentsOf to silently fail, skipping all commitment payouts.
|
|
424
|
-
// slither-disable-next-line incorrect-equality
|
|
425
429
|
if (launchProjectData.token.token != JBConstants.NATIVE_TOKEN && launchProjectData.token.currency == 0) {
|
|
426
|
-
revert DefifaDeployer_InvalidCurrency(
|
|
430
|
+
revert DefifaDeployer_InvalidCurrency({
|
|
431
|
+
token: launchProjectData.token.token, currency: launchProjectData.token.currency
|
|
432
|
+
});
|
|
427
433
|
}
|
|
428
434
|
|
|
429
435
|
// If a scorecard timeout is set, it must exceed the full ratification window:
|
|
@@ -437,7 +443,14 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
437
443
|
if (
|
|
438
444
|
launchProjectData.scorecardTimeout
|
|
439
445
|
<= attestationDelay + launchProjectData.attestationGracePeriod + launchProjectData.timelockDuration
|
|
440
|
-
)
|
|
446
|
+
) {
|
|
447
|
+
revert DefifaDeployer_InvalidGameConfiguration({
|
|
448
|
+
start: launchProjectData.start,
|
|
449
|
+
mintPeriodDuration: launchProjectData.mintPeriodDuration,
|
|
450
|
+
refundPeriodDuration: launchProjectData.refundPeriodDuration,
|
|
451
|
+
tierCount: launchProjectData.tiers.length
|
|
452
|
+
});
|
|
453
|
+
}
|
|
441
454
|
}
|
|
442
455
|
|
|
443
456
|
// Reserve the game ID up front so permissionless project creations cannot invalidate hook deployment.
|
|
@@ -542,7 +555,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
542
555
|
}
|
|
543
556
|
|
|
544
557
|
// Increment the nonce for this deployment.
|
|
545
|
-
// slither-disable-next-line reentrancy-benign
|
|
546
558
|
uint256 currentNonce = ++_nonce;
|
|
547
559
|
|
|
548
560
|
// Clone deterministically using sender and nonce to prevent front-running.
|
|
@@ -601,8 +613,9 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
601
613
|
bytecode: _cloneCreationCodeFor(address(HOOK_CODE_ORIGIN))
|
|
602
614
|
});
|
|
603
615
|
|
|
604
|
-
|
|
605
|
-
|
|
616
|
+
emit LaunchGame({
|
|
617
|
+
gameId: gameId, hook: hook, governor: GOVERNOR, tokenUriResolver: uriResolver, caller: msg.sender
|
|
618
|
+
});
|
|
606
619
|
}
|
|
607
620
|
|
|
608
621
|
/// @notice Allows this contract to receive 721s.
|
|
@@ -617,12 +630,13 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
617
630
|
/// @param gameId The ID of the game to trigger no-contest for.
|
|
618
631
|
function triggerNoContestFor(uint256 gameId) external override {
|
|
619
632
|
// Make sure the game is currently in NO_CONTEST phase.
|
|
620
|
-
|
|
621
|
-
|
|
633
|
+
DefifaGamePhase phase = currentGamePhaseOf(gameId);
|
|
634
|
+
if (phase != DefifaGamePhase.NO_CONTEST) {
|
|
635
|
+
revert DefifaDeployer_NotNoContest({gameId: gameId, phase: phase});
|
|
622
636
|
}
|
|
623
637
|
|
|
624
638
|
// Make sure no-contest hasn't already been triggered.
|
|
625
|
-
if (noContestTriggeredFor[gameId]) revert DefifaDeployer_NoContestAlreadyTriggered();
|
|
639
|
+
if (noContestTriggeredFor[gameId]) revert DefifaDeployer_NoContestAlreadyTriggered({gameId: gameId});
|
|
626
640
|
|
|
627
641
|
// Mark as triggered.
|
|
628
642
|
// Note: the queued ruleset does not take effect until the current ruleset's cycle ends (or immediately
|
|
@@ -632,7 +646,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
632
646
|
noContestTriggeredFor[gameId] = true;
|
|
633
647
|
|
|
634
648
|
// Get the game's current ruleset metadata for the data hook address.
|
|
635
|
-
// slither-disable-next-line unused-return
|
|
636
649
|
(, JBRulesetMetadata memory metadata) = CONTROLLER.currentRulesetOf(gameId);
|
|
637
650
|
|
|
638
651
|
// Queue a new ruleset without payout limits so surplus = balance, enabling refunds.
|
|
@@ -658,7 +671,7 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
658
671
|
allowAddPriceFeed: false,
|
|
659
672
|
ownerMustSendPayouts: true,
|
|
660
673
|
holdFees: false,
|
|
661
|
-
|
|
674
|
+
scopeCashOutsToLocalBalances: true,
|
|
662
675
|
useDataHookForPay: true,
|
|
663
676
|
useDataHookForCashOut: true,
|
|
664
677
|
dataHook: metadata.dataHook,
|
|
@@ -673,13 +686,11 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
673
686
|
});
|
|
674
687
|
|
|
675
688
|
// Queue the no-contest refund ruleset.
|
|
676
|
-
// slither-disable-next-line unused-return
|
|
677
689
|
CONTROLLER.queueRulesetsOf({
|
|
678
690
|
projectId: gameId, rulesetConfigurations: rulesetConfigs, memo: "Defifa game: no contest."
|
|
679
691
|
});
|
|
680
692
|
|
|
681
|
-
|
|
682
|
-
emit QueuedNoContest(gameId, msg.sender);
|
|
693
|
+
emit QueuedNoContest({gameId: gameId, caller: msg.sender});
|
|
683
694
|
}
|
|
684
695
|
|
|
685
696
|
//*********************************************************************//
|
|
@@ -711,10 +722,13 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
711
722
|
}
|
|
712
723
|
|
|
713
724
|
// Validate that total fee splits don't exceed 100%.
|
|
714
|
-
if (totalAbsolutePercent > JBConstants.SPLITS_TOTAL_PERCENT)
|
|
725
|
+
if (totalAbsolutePercent > JBConstants.SPLITS_TOTAL_PERCENT) {
|
|
726
|
+
revert DefifaDeployer_SplitsDontAddUp({
|
|
727
|
+
totalPercent: totalAbsolutePercent, maxPercent: JBConstants.SPLITS_TOTAL_PERCENT
|
|
728
|
+
});
|
|
729
|
+
}
|
|
715
730
|
|
|
716
731
|
// Store the total absolute percent for use in fulfillCommitmentsOf.
|
|
717
|
-
// slither-disable-next-line reentrancy-benign
|
|
718
732
|
_commitmentPercentOf[gameId] = totalAbsolutePercent;
|
|
719
733
|
|
|
720
734
|
// Build the splits array: user splits + Defifa + NANA (NANA last to absorb rounding).
|
|
@@ -820,7 +834,7 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
820
834
|
allowAddPriceFeed: false,
|
|
821
835
|
ownerMustSendPayouts: false,
|
|
822
836
|
holdFees: false,
|
|
823
|
-
|
|
837
|
+
scopeCashOutsToLocalBalances: true,
|
|
824
838
|
useDataHookForPay: true,
|
|
825
839
|
useDataHookForCashOut: true,
|
|
826
840
|
dataHook: dataHook,
|
|
@@ -863,7 +877,7 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
863
877
|
allowAddPriceFeed: false,
|
|
864
878
|
ownerMustSendPayouts: false,
|
|
865
879
|
holdFees: false,
|
|
866
|
-
|
|
880
|
+
scopeCashOutsToLocalBalances: true,
|
|
867
881
|
useDataHookForPay: true,
|
|
868
882
|
useDataHookForCashOut: true,
|
|
869
883
|
dataHook: dataHook,
|
|
@@ -923,7 +937,7 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
923
937
|
// Set this to true so only the deployer can fulfill the commitments.
|
|
924
938
|
ownerMustSendPayouts: true,
|
|
925
939
|
holdFees: false,
|
|
926
|
-
|
|
940
|
+
scopeCashOutsToLocalBalances: true,
|
|
927
941
|
useDataHookForPay: true,
|
|
928
942
|
useDataHookForCashOut: true,
|
|
929
943
|
dataHook: dataHook,
|
|
@@ -943,7 +957,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
943
957
|
});
|
|
944
958
|
|
|
945
959
|
// Launch the rulesets for the reserved project and set the project URI in the same controller call.
|
|
946
|
-
// slither-disable-next-line unused-return
|
|
947
960
|
CONTROLLER.launchRulesetsFor({
|
|
948
961
|
projectId: gameId,
|
|
949
962
|
projectUri: launchProjectData.projectUri,
|
|
@@ -979,7 +992,7 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
979
992
|
allowAddPriceFeed: false,
|
|
980
993
|
ownerMustSendPayouts: false,
|
|
981
994
|
holdFees: false,
|
|
982
|
-
|
|
995
|
+
scopeCashOutsToLocalBalances: true,
|
|
983
996
|
useDataHookForPay: true,
|
|
984
997
|
useDataHookForCashOut: true,
|
|
985
998
|
dataHook: metadata.dataHook,
|
|
@@ -994,7 +1007,6 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
994
1007
|
fundAccessLimitGroups: new JBFundAccessLimitGroup[](0)
|
|
995
1008
|
});
|
|
996
1009
|
|
|
997
|
-
// slither-disable-next-line unused-return
|
|
998
1010
|
CONTROLLER.queueRulesetsOf({
|
|
999
1011
|
projectId: gameId, rulesetConfigurations: rulesetConfigs, memo: "Defifa game has finished."
|
|
1000
1012
|
});
|