@ballkidz/defifa 0.0.39 → 0.0.41
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 +3 -0
- package/CHANGELOG.md +8 -0
- package/package.json +2 -2
- package/script/Deploy.s.sol +2 -1
- package/src/DefifaDeployer.sol +63 -6
- package/src/interfaces/IDefifaDeployer.sol +22 -0
package/ADMINISTRATION.md
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
| Ratification path caller | Any caller who meets the documented conditions | Per game | Finalizes a valid scorecard |
|
|
31
31
|
| Fulfillment path caller | Any valid caller once ratified | Per game | Must run the completion commitment path |
|
|
32
32
|
| `DefifaProjectOwner` holder | Project NFT sent into sink | Per fee project | Irreversible ownership lock |
|
|
33
|
+
| `DefifaDeployer` owner | Constructor `initialOwner` (typically the Defifa multisig) | Global referral-attribution surface | Single privilege: call `setReferralProjectId` to repoint the fee-volume credit |
|
|
33
34
|
|
|
34
35
|
## Privileged Surfaces
|
|
35
36
|
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
- `submitScorecardFor(...)`, `attestToScorecardFrom(...)`, `revokeAttestationFrom(...)`, and `ratifyScorecardFrom(...)` govern outcome selection
|
|
38
39
|
- `fulfillCommitmentsOf(...)` turns a ratified scorecard into real settlement
|
|
39
40
|
- `triggerNoContestFor(...)` moves failed games into the documented recovery path
|
|
41
|
+
- `DefifaDeployer.setReferralProjectId(projectId, chainId)` — `onlyOwner`; retargets the fee-volume referrer credited on every `sendPayoutsOf` call this deployer makes from `fulfillCommitmentsOf`. Stores the packed `(chainId << 48) | projectId` value `JBMultiTerminal` expects on its `referralProjectId` argument. Defaults to `(1, DEFIFA_PROJECT_ID)` at construction so credit lands on the Defifa project on Ethereum mainnet regardless of which chain a game runs on. Passing `(0, 0)` disables the credit entirely. Bounded so the pack is lossless: `projectId <= type(uint48).max`, `chainId <= type(uint208).max`. Does not affect game economics — only where fee-volume attribution accrues.
|
|
40
42
|
|
|
41
43
|
## Immutable And One-Way
|
|
42
44
|
|
|
@@ -77,3 +79,4 @@
|
|
|
77
79
|
- No one can set cash-out weights twice.
|
|
78
80
|
- No one can fulfill commitments twice.
|
|
79
81
|
- No one can recover the project NFT from `DefifaProjectOwner`.
|
|
82
|
+
- The `DefifaDeployer` owner can repoint `referralProjectId` but cannot change anything else about an in-flight or past game — game economics, fees, and settlement remain bounded by the immutable launch configuration.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.0.41 — Owner-settable referral target on `DefifaDeployer`
|
|
4
|
+
|
|
5
|
+
- `DefifaDeployer` now inherits OpenZeppelin `Ownable`. New constructor arg `address initialOwner` is passed straight to `Ownable(initialOwner)`. **This is a breaking constructor signature change** — `script/Deploy.s.sol` and every test that instantiates `DefifaDeployer` directly was updated to pass `initialOwner` (typically `safeAddress()` in the deploy script; `address(this)` in tests).
|
|
6
|
+
- New `referralProjectId()` view returning the packed `(chainId << 48) | projectId` reference credited as the referrer on every fee-payout `sendPayoutsOf` call from `fulfillCommitmentsOf`.
|
|
7
|
+
- New `setReferralProjectId(uint256 projectId, uint256 chainId)` (`onlyOwner`): takes the two fields unpacked, packs and stores them. Bounded so the pack is lossless — `projectId <= type(uint48).max`, `chainId <= type(uint208).max`. Reverts with `DefifaDeployer_ReferralProjectIdTooLarge` / `DefifaDeployer_ReferralChainIdTooLarge` otherwise. Emits `SetReferralProjectId(referralChainId, referralProjectId, caller)`.
|
|
8
|
+
- Default at construction: `(chainId = 1, projectId = DEFIFA_PROJECT_ID)` — fee-volume credit still lands on the Defifa project on Ethereum mainnet regardless of which chain a game runs on. Owner can repoint this or pass `(0, 0)` to disable referral credit entirely.
|
|
9
|
+
- The inline `(uint256(1) << 48) | DEFIFA_PROJECT_ID` pack inside `fulfillCommitmentsOf` is replaced by a read of the new storage slot. No external behavior change for default deployments.
|
|
10
|
+
|
|
3
11
|
## 0.0.35 — Bump v6 deps to nana-core-v6 0.0.53 cohort
|
|
4
12
|
|
|
5
13
|
- `@bananapus/core-v6`: `^0.0.48 → ^0.0.53` ([PR #145](https://github.com/Bananapus/nana-core-v6/pull/145)).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ballkidz/defifa",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.41",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "25.9.0"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@bananapus/721-hook-v6": "^0.0.54",
|
|
35
35
|
"@bananapus/address-registry-v6": "^0.0.26",
|
|
36
|
-
"@bananapus/core-v6": "^0.0.
|
|
36
|
+
"@bananapus/core-v6": "^0.0.59",
|
|
37
37
|
"@bananapus/permission-ids-v6": "^0.0.26",
|
|
38
38
|
"@openzeppelin/contracts": "5.6.1",
|
|
39
39
|
"@prb/math": "4.1.1",
|
package/script/Deploy.s.sol
CHANGED
|
@@ -119,7 +119,8 @@ contract DeployMainnet is Script, Sphinx {
|
|
|
119
119
|
registry: registry.registry,
|
|
120
120
|
defifaProjectId: _defifaProjectId,
|
|
121
121
|
baseProtocolProjectId: _baseProtocolProjectId,
|
|
122
|
-
hookStore: hookStore
|
|
122
|
+
hookStore: hookStore,
|
|
123
|
+
initialOwner: safeAddress()
|
|
123
124
|
});
|
|
124
125
|
|
|
125
126
|
governor.transferOwnership(address(deployer));
|
package/src/DefifaDeployer.sol
CHANGED
|
@@ -21,6 +21,7 @@ import {JBFundAccessLimitGroup} from "@bananapus/core-v6/src/structs/JBFundAcces
|
|
|
21
21
|
import {JBRulesetMetadata} from "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
22
22
|
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
23
23
|
import {JBSplitGroup} from "@bananapus/core-v6/src/structs/JBSplitGroup.sol";
|
|
24
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
24
25
|
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
|
|
25
26
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
26
27
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
@@ -46,7 +47,7 @@ import {DefifaTierParams} from "./structs/DefifaTierParams.sol";
|
|
|
46
47
|
/// the event concludes, a scorecard assigns cash-out weights to each tier. The treasury is distributed proportionally
|
|
47
48
|
/// to winning NFT holders. Games progress through phases: COUNTDOWN → MINT → REFUND → SCORING → COMPLETE (or
|
|
48
49
|
/// NO_CONTEST if minimum participation isn't met or scorecard ratification times out).
|
|
49
|
-
contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGamePotReporter, IERC721Receiver {
|
|
50
|
+
contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGamePotReporter, IERC721Receiver, Ownable {
|
|
50
51
|
using Strings for uint256;
|
|
51
52
|
using SafeERC20 for IERC20;
|
|
52
53
|
|
|
@@ -61,6 +62,8 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
61
62
|
error DefifaDeployer_InvalidCurrency(address token, uint256 currency);
|
|
62
63
|
error DefifaDeployer_NotNoContest(uint256 gameId, DefifaGamePhase phase);
|
|
63
64
|
error DefifaDeployer_NoContestAlreadyTriggered(uint256 gameId);
|
|
65
|
+
error DefifaDeployer_ReferralChainIdTooLarge(uint256 referralChainId);
|
|
66
|
+
error DefifaDeployer_ReferralProjectIdTooLarge(uint256 referralProjectId);
|
|
64
67
|
error DefifaDeployer_SplitsDontAddUp(uint256 totalPercent, uint256 maxPercent);
|
|
65
68
|
|
|
66
69
|
//*********************************************************************//
|
|
@@ -133,6 +136,12 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
133
136
|
/// @dev Once triggered, the game stays in NO_CONTEST and refunds are enabled.
|
|
134
137
|
mapping(uint256 => bool) public noContestTriggeredFor;
|
|
135
138
|
|
|
139
|
+
/// @notice The packed `(referralChainId << 48) | referralProjectId` reference credited as the referrer on
|
|
140
|
+
/// every fee-payout `sendPayoutsOf` call this deployer makes during `fulfillCommitmentsOf`. Defaults to
|
|
141
|
+
/// `(1, DEFIFA_PROJECT_ID)` so fee-volume credit accrues to the Defifa project on Ethereum mainnet
|
|
142
|
+
/// regardless of which chain the game runs on. Settable by the owner via `setReferralProjectId`.
|
|
143
|
+
uint256 public override referralProjectId;
|
|
144
|
+
|
|
136
145
|
//*********************************************************************//
|
|
137
146
|
// ------------------------- external views -------------------------- //
|
|
138
147
|
//*********************************************************************//
|
|
@@ -281,6 +290,9 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
281
290
|
/// @param defifaProjectId The ID of the project that should take the fee from the games.
|
|
282
291
|
/// @param baseProtocolProjectId The ID of the protocol project that'll receive fees from fulfilling commitments.
|
|
283
292
|
/// @param hookStore The store used by Defifa hooks.
|
|
293
|
+
/// @param initialOwner The address granted authority to call `setReferralProjectId`. The contract is otherwise
|
|
294
|
+
/// stateless from an admin perspective — the owner only controls the referrer reference used when crediting
|
|
295
|
+
/// fee-volume on `fulfillCommitmentsOf` payouts.
|
|
284
296
|
constructor(
|
|
285
297
|
address hookCodeOrigin,
|
|
286
298
|
IJB721TokenUriResolver tokenUriResolver,
|
|
@@ -289,8 +301,11 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
289
301
|
IJBAddressRegistry registry,
|
|
290
302
|
uint256 defifaProjectId,
|
|
291
303
|
uint256 baseProtocolProjectId,
|
|
292
|
-
IJB721TiersHookStore hookStore
|
|
293
|
-
|
|
304
|
+
IJB721TiersHookStore hookStore,
|
|
305
|
+
address initialOwner
|
|
306
|
+
)
|
|
307
|
+
Ownable(initialOwner)
|
|
308
|
+
{
|
|
294
309
|
HOOK_CODE_ORIGIN = hookCodeOrigin;
|
|
295
310
|
TOKEN_URI_RESOLVER = tokenUriResolver;
|
|
296
311
|
GOVERNOR = governor;
|
|
@@ -301,6 +316,10 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
301
316
|
HOOK_STORE = hookStore;
|
|
302
317
|
/// @dev Uses the deployer address as group ID. Game scoring rulesets use uint160(token) as group ID.
|
|
303
318
|
SPLIT_GROUP = uint256(uint160(address(this)));
|
|
319
|
+
|
|
320
|
+
// Default referrer reference: Defifa project on Ethereum mainnet. Encoded `(chainId << 48) | projectId`
|
|
321
|
+
// per `JBMultiTerminal.currentReferralProjectId`. Owner can retarget via `setReferralProjectId`.
|
|
322
|
+
referralProjectId = (uint256(1) << 48) | defifaProjectId;
|
|
304
323
|
}
|
|
305
324
|
|
|
306
325
|
//*********************************************************************//
|
|
@@ -346,10 +365,18 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
346
365
|
|
|
347
366
|
// Send only the fee portion as payouts. The remaining balance stays as surplus for cash-outs.
|
|
348
367
|
// Use the ruleset's baseCurrency — this matches the currency under which payout limits were stored
|
|
349
|
-
// at launch time, regardless of whether the token is native ETH or an ERC-20.
|
|
350
|
-
//
|
|
368
|
+
// at launch time, regardless of whether the token is native ETH or an ERC-20. Wrapped in try-catch so
|
|
369
|
+
// the final ruleset is always queued even if payout fails. The configured `referralProjectId` (default
|
|
370
|
+
// `(1, DEFIFA_PROJECT_ID)`, owner-settable via `setReferralProjectId`) credits Defifa with the protocol
|
|
371
|
+
// fee volume from every game's commitment payout. Pinning mainnet by default avoids scattering credit
|
|
372
|
+
// across L2s where Defifa has no canonical project ID.
|
|
351
373
|
try terminal.sendPayoutsOf({
|
|
352
|
-
projectId: gameId,
|
|
374
|
+
projectId: gameId,
|
|
375
|
+
token: token,
|
|
376
|
+
amount: feeAmount,
|
|
377
|
+
currency: metadata.baseCurrency,
|
|
378
|
+
minTokensPaidOut: 0,
|
|
379
|
+
referralProjectId: referralProjectId
|
|
353
380
|
}) {}
|
|
354
381
|
catch (bytes memory reason) {
|
|
355
382
|
// Payout failed — fee stays in pot. Reset to 0 so currentGamePotOf
|
|
@@ -639,6 +666,36 @@ contract DefifaDeployer is IDefifaDeployer, IDefifaGamePhaseReporter, IDefifaGam
|
|
|
639
666
|
return IERC721Receiver.onERC721Received.selector;
|
|
640
667
|
}
|
|
641
668
|
|
|
669
|
+
/// @notice Update the referrer reference credited on every fee-payout `sendPayoutsOf` call this deployer
|
|
670
|
+
/// makes during `fulfillCommitmentsOf`.
|
|
671
|
+
/// @dev Stores the packed `(newReferralChainId << 48) | newReferralProjectId` value used by
|
|
672
|
+
/// `JBMultiTerminal.currentReferralProjectId`. Either field may be zero — passing `(0, 0)` disables the
|
|
673
|
+
/// referral credit entirely. Bounded so the pack is lossless: `newReferralProjectId` must fit in `uint48`,
|
|
674
|
+
/// `newReferralChainId` must fit in `uint208` (so the left-shift by 48 doesn't drop high bits).
|
|
675
|
+
/// @param newReferralProjectId The referring project's bare ID on `newReferralChainId`.
|
|
676
|
+
/// @param newReferralChainId The EIP-155 chain ID of the referrer's home chain.
|
|
677
|
+
function setReferralProjectId(
|
|
678
|
+
uint256 newReferralProjectId,
|
|
679
|
+
uint256 newReferralChainId
|
|
680
|
+
)
|
|
681
|
+
external
|
|
682
|
+
override
|
|
683
|
+
onlyOwner
|
|
684
|
+
{
|
|
685
|
+
// Bound the inputs to the on-chain encoding so the pack is lossless. The same shape JBMultiTerminal uses:
|
|
686
|
+
// projectId in bits [47:0], chainId in bits [255:48].
|
|
687
|
+
if (newReferralProjectId > type(uint48).max) {
|
|
688
|
+
revert DefifaDeployer_ReferralProjectIdTooLarge(newReferralProjectId);
|
|
689
|
+
}
|
|
690
|
+
if (newReferralChainId >> 208 != 0) revert DefifaDeployer_ReferralChainIdTooLarge(newReferralChainId);
|
|
691
|
+
|
|
692
|
+
referralProjectId = (newReferralChainId << 48) | newReferralProjectId;
|
|
693
|
+
|
|
694
|
+
emit SetReferralProjectId({
|
|
695
|
+
referralChainId: newReferralChainId, referralProjectId: newReferralProjectId, caller: msg.sender
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
|
|
642
699
|
/// @notice Triggers the no-contest refund mechanism for a game.
|
|
643
700
|
/// @dev Anyone can call this once the game is in the NO_CONTEST phase. This queues a new ruleset without
|
|
644
701
|
/// payout limits, making the surplus equal to the balance so users can cash out at their mint price.
|
|
@@ -45,6 +45,12 @@ interface IDefifaDeployer {
|
|
|
45
45
|
/// @param caller The address that queued the phase transition.
|
|
46
46
|
event QueuedNoContest(uint256 indexed gameId, address caller);
|
|
47
47
|
|
|
48
|
+
/// @notice Emitted when the referrer reference for fee-volume credit is updated.
|
|
49
|
+
/// @param referralChainId The EIP-155 chain ID of the new referrer's home chain.
|
|
50
|
+
/// @param referralProjectId The new referring project's bare project ID on `referralChainId`.
|
|
51
|
+
/// @param caller The address that set the new referrer.
|
|
52
|
+
event SetReferralProjectId(uint256 indexed referralChainId, uint256 indexed referralProjectId, address caller);
|
|
53
|
+
|
|
48
54
|
/// @notice The fee divisor for base protocol fees (100 / fee percent).
|
|
49
55
|
/// @return The fee divisor.
|
|
50
56
|
function BASE_PROTOCOL_FEE_DIVISOR() external view returns (uint256);
|
|
@@ -81,6 +87,12 @@ interface IDefifaDeployer {
|
|
|
81
87
|
/// @return The address registry contract.
|
|
82
88
|
function REGISTRY() external view returns (IJBAddressRegistry);
|
|
83
89
|
|
|
90
|
+
/// @notice The packed `(referralChainId << 48) | referralProjectId` reference credited as the referrer on
|
|
91
|
+
/// every fee-payout `sendPayoutsOf` call this deployer makes. Defaults to `(1, DEFIFA_PROJECT_ID)` so
|
|
92
|
+
/// credit accrues to Defifa on Ethereum mainnet; owner-settable via `setReferralProjectId`.
|
|
93
|
+
/// @return The packed referrer reference.
|
|
94
|
+
function referralProjectId() external view returns (uint256);
|
|
95
|
+
|
|
84
96
|
/// @notice The split group ID used for distributing game pot funds.
|
|
85
97
|
/// @return The split group.
|
|
86
98
|
function SPLIT_GROUP() external view returns (uint256);
|
|
@@ -119,6 +131,16 @@ interface IDefifaDeployer {
|
|
|
119
131
|
/// @return gameId The ID of the newly launched game.
|
|
120
132
|
function launchGameWith(DefifaLaunchProjectData calldata launchProjectData) external returns (uint256 gameId);
|
|
121
133
|
|
|
134
|
+
/// @notice Update the referrer reference credited on every fee-payout `sendPayoutsOf` call this deployer
|
|
135
|
+
/// makes during `fulfillCommitmentsOf`.
|
|
136
|
+
/// @dev Stores the packed `(newReferralChainId << 48) | newReferralProjectId` value used by
|
|
137
|
+
/// `JBMultiTerminal.currentReferralProjectId`. Either field may be zero (passing `(0, 0)` disables the
|
|
138
|
+
/// referral credit). Bounded so the pack is lossless: `newReferralProjectId <= type(uint48).max`,
|
|
139
|
+
/// `newReferralChainId <= type(uint208).max`.
|
|
140
|
+
/// @param newReferralProjectId The referring project's bare ID on `newReferralChainId`.
|
|
141
|
+
/// @param newReferralChainId The EIP-155 chain ID of the referrer's home chain.
|
|
142
|
+
function setReferralProjectId(uint256 newReferralProjectId, uint256 newReferralChainId) external;
|
|
143
|
+
|
|
122
144
|
/// @notice Trigger a no-contest outcome for a game.
|
|
123
145
|
/// @param gameId The ID of the game.
|
|
124
146
|
function triggerNoContestFor(uint256 gameId) external;
|