@ballkidz/defifa 0.0.7 → 0.0.9
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 -3
- package/ARCHITECTURE.md +2 -0
- package/AUDIT_INSTRUCTIONS.md +422 -0
- package/CRYPTO_ECON.md +5 -5
- package/README.md +1 -1
- package/RISKS.md +38 -335
- package/SKILLS.md +1 -1
- package/USER_JOURNEYS.md +691 -0
- package/package.json +7 -7
- package/script/Deploy.s.sol +14 -3
- package/script/helpers/DefifaDeploymentLib.sol +13 -15
- package/src/DefifaDeployer.sol +221 -192
- package/src/DefifaGovernor.sol +286 -276
- package/src/DefifaHook.sol +68 -34
- package/src/DefifaProjectOwner.sol +27 -4
- package/src/DefifaTokenUriResolver.sol +136 -134
- package/src/enums/DefifaGamePhase.sol +1 -1
- package/src/enums/DefifaScorecardState.sol +1 -1
- package/src/interfaces/IDefifaDeployer.sol +52 -50
- package/src/interfaces/IDefifaGamePhaseReporter.sol +2 -2
- package/src/interfaces/IDefifaGamePotReporter.sol +1 -1
- package/src/interfaces/IDefifaGovernor.sol +53 -54
- package/src/interfaces/IDefifaHook.sol +104 -103
- package/src/interfaces/IDefifaTokenUriResolver.sol +2 -2
- package/src/libraries/DefifaFontImporter.sol +11 -9
- package/src/libraries/DefifaHookLib.sol +66 -53
- package/src/structs/DefifaAttestations.sol +1 -1
- package/src/structs/DefifaDelegation.sol +1 -1
- package/src/structs/DefifaLaunchProjectData.sol +4 -4
- package/src/structs/DefifaOpsData.sol +1 -1
- package/src/structs/DefifaScorecard.sol +1 -1
- package/src/structs/DefifaTierCashOutWeight.sol +1 -1
- package/src/structs/DefifaTierParams.sol +2 -1
- package/test/DefifaAdversarialQuorum.t.sol +602 -0
- package/test/DefifaAuditLowGuards.t.sol +304 -0
- package/test/DefifaFeeAccounting.t.sol +37 -16
- package/test/DefifaGovernor.t.sol +43 -19
- package/test/DefifaHookRegressions.t.sol +14 -12
- package/test/DefifaMintCostInvariant.t.sol +31 -12
- package/test/DefifaNoContest.t.sol +34 -16
- package/test/DefifaSecurity.t.sol +46 -28
- package/test/DefifaUSDC.t.sol +45 -36
- package/test/Fork.t.sol +43 -43
- package/test/SVG.t.sol +2 -2
- package/test/TestAuditGaps.sol +982 -0
- package/test/TestQALastMile.t.sol +511 -0
- package/test/regression/FulfillmentBlocksRatification.t.sol +36 -30
- package/test/regression/GracePeriodBypass.t.sol +15 -10
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
// SPDX-License-Identifier: UNLICENSED
|
|
2
|
+
pragma solidity 0.8.26;
|
|
3
|
+
|
|
4
|
+
import {TestBaseWorkflow} from "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
|
|
5
|
+
|
|
6
|
+
import {DefifaGovernor} from "../src/DefifaGovernor.sol";
|
|
7
|
+
import {DefifaDeployer} from "../src/DefifaDeployer.sol";
|
|
8
|
+
import {DefifaHook} from "../src/DefifaHook.sol";
|
|
9
|
+
import {DefifaTokenUriResolver} from "../src/DefifaTokenUriResolver.sol";
|
|
10
|
+
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
11
|
+
|
|
12
|
+
import {JBTest} from "@bananapus/core-v6/test/helpers/JBTest.sol";
|
|
13
|
+
import {JBRulesetMetadataResolver} from "@bananapus/core-v6/src/libraries/JBRulesetMetadataResolver.sol";
|
|
14
|
+
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
15
|
+
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
16
|
+
|
|
17
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
18
|
+
import {ITypeface} from "lib/typeface/contracts/interfaces/ITypeface.sol";
|
|
19
|
+
import {IJB721TokenUriResolver} from "@bananapus/721-hook-v6/src/interfaces/IJB721TokenUriResolver.sol";
|
|
20
|
+
import {DefifaDelegation} from "../src/structs/DefifaDelegation.sol";
|
|
21
|
+
import {DefifaLaunchProjectData} from "../src/structs/DefifaLaunchProjectData.sol";
|
|
22
|
+
import {DefifaTierParams} from "../src/structs/DefifaTierParams.sol";
|
|
23
|
+
import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
24
|
+
import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
25
|
+
import {JBCurrencyIds} from "@bananapus/core-v6/src/libraries/JBCurrencyIds.sol";
|
|
26
|
+
import {JBFundAccessLimitGroup} from "@bananapus/core-v6/src/structs/JBFundAccessLimitGroup.sol";
|
|
27
|
+
import {JBRulesetConfig, JBTerminalConfig} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
|
|
28
|
+
import {JBRulesetMetadata} from "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
29
|
+
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
30
|
+
import {JBSplitGroup} from "@bananapus/core-v6/src/structs/JBSplitGroup.sol";
|
|
31
|
+
import {IJBRulesetApprovalHook} from "@bananapus/core-v6/src/interfaces/IJBRulesets.sol";
|
|
32
|
+
|
|
33
|
+
/// @title DefifaAuditLowGuardsTest
|
|
34
|
+
/// @notice Tests for validation guards added in the audit/low-findings branch:
|
|
35
|
+
/// - DefifaGovernor_AlreadyInitialized (re-initialization guard)
|
|
36
|
+
/// - uint48 overflow checks on attestationStartTime and attestationGracePeriod
|
|
37
|
+
/// - DefifaHook_DelegateAddressZero (address(0) delegation guard)
|
|
38
|
+
contract DefifaAuditLowGuardsTest is JBTest, TestBaseWorkflow {
|
|
39
|
+
using JBRulesetMetadataResolver for JBRuleset;
|
|
40
|
+
|
|
41
|
+
address _protocolFeeProjectTokenAccount;
|
|
42
|
+
address _defifaProjectTokenAccount;
|
|
43
|
+
uint256 _protocolFeeProjectId;
|
|
44
|
+
uint256 _defifaProjectId;
|
|
45
|
+
uint256 _gameId = 3;
|
|
46
|
+
|
|
47
|
+
DefifaDeployer deployer;
|
|
48
|
+
DefifaHook hook;
|
|
49
|
+
DefifaGovernor governor;
|
|
50
|
+
address projectOwner = address(bytes20(keccak256("projectOwner")));
|
|
51
|
+
|
|
52
|
+
// Shared test state (set by _setupGame)
|
|
53
|
+
uint256 _pid;
|
|
54
|
+
DefifaHook _nft;
|
|
55
|
+
DefifaGovernor _gov;
|
|
56
|
+
address[] _users;
|
|
57
|
+
|
|
58
|
+
function setUp() public virtual override {
|
|
59
|
+
super.setUp();
|
|
60
|
+
|
|
61
|
+
JBAccountingContext[] memory _tokens = new JBAccountingContext[](1);
|
|
62
|
+
_tokens[0] = JBAccountingContext({token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: JBCurrencyIds.ETH});
|
|
63
|
+
JBTerminalConfig[] memory tc = new JBTerminalConfig[](1);
|
|
64
|
+
tc[0] = JBTerminalConfig({terminal: jbMultiTerminal(), accountingContextsToAccept: _tokens});
|
|
65
|
+
JBRulesetConfig[] memory rc = new JBRulesetConfig[](1);
|
|
66
|
+
rc[0] = JBRulesetConfig({
|
|
67
|
+
mustStartAtOrAfter: 0,
|
|
68
|
+
duration: 10 days,
|
|
69
|
+
weight: 1e18,
|
|
70
|
+
weightCutPercent: 0,
|
|
71
|
+
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
72
|
+
metadata: JBRulesetMetadata({
|
|
73
|
+
reservedPercent: 0,
|
|
74
|
+
cashOutTaxRate: 0,
|
|
75
|
+
baseCurrency: JBCurrencyIds.ETH,
|
|
76
|
+
pausePay: false,
|
|
77
|
+
pauseCreditTransfers: false,
|
|
78
|
+
allowOwnerMinting: false,
|
|
79
|
+
allowSetCustomToken: false,
|
|
80
|
+
allowTerminalMigration: false,
|
|
81
|
+
allowSetTerminals: false,
|
|
82
|
+
allowSetController: false,
|
|
83
|
+
allowAddAccountingContext: false,
|
|
84
|
+
allowAddPriceFeed: false,
|
|
85
|
+
ownerMustSendPayouts: false,
|
|
86
|
+
holdFees: false,
|
|
87
|
+
useTotalSurplusForCashOuts: false,
|
|
88
|
+
useDataHookForPay: true,
|
|
89
|
+
useDataHookForCashOut: true,
|
|
90
|
+
dataHook: address(0),
|
|
91
|
+
metadata: 0
|
|
92
|
+
}),
|
|
93
|
+
splitGroups: new JBSplitGroup[](0),
|
|
94
|
+
fundAccessLimitGroups: new JBFundAccessLimitGroup[](0)
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
_protocolFeeProjectId = jbController().launchProjectFor(projectOwner, "", rc, tc, "");
|
|
98
|
+
vm.prank(projectOwner);
|
|
99
|
+
_protocolFeeProjectTokenAccount =
|
|
100
|
+
address(jbController().deployERC20For(_protocolFeeProjectId, "Bananapus", "NANA", bytes32(0)));
|
|
101
|
+
_defifaProjectId = jbController().launchProjectFor(projectOwner, "", rc, tc, "");
|
|
102
|
+
vm.prank(projectOwner);
|
|
103
|
+
_defifaProjectTokenAccount =
|
|
104
|
+
address(jbController().deployERC20For(_defifaProjectId, "Defifa", "DEFIFA", bytes32(0)));
|
|
105
|
+
|
|
106
|
+
hook =
|
|
107
|
+
new DefifaHook(jbDirectory(), IERC20(_defifaProjectTokenAccount), IERC20(_protocolFeeProjectTokenAccount));
|
|
108
|
+
governor = new DefifaGovernor(jbController(), address(this));
|
|
109
|
+
deployer = new DefifaDeployer(
|
|
110
|
+
address(hook),
|
|
111
|
+
new DefifaTokenUriResolver(ITypeface(address(0))),
|
|
112
|
+
governor,
|
|
113
|
+
jbController(),
|
|
114
|
+
new JBAddressRegistry(),
|
|
115
|
+
_protocolFeeProjectId,
|
|
116
|
+
_defifaProjectId
|
|
117
|
+
);
|
|
118
|
+
hook.transferOwnership(address(deployer));
|
|
119
|
+
governor.transferOwnership(address(deployer));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// =========================================================================
|
|
123
|
+
// 1. DefifaGovernor_AlreadyInitialized: re-initialization blocked
|
|
124
|
+
// =========================================================================
|
|
125
|
+
function testRevert_initializeGame_alreadyInitialized() external {
|
|
126
|
+
// Deploy a standalone governor where this test contract is the owner, so we can call initializeGame directly.
|
|
127
|
+
DefifaGovernor _standaloneGov = new DefifaGovernor(jbController(), address(this));
|
|
128
|
+
|
|
129
|
+
// First initialization should succeed.
|
|
130
|
+
uint256 gameId = 42;
|
|
131
|
+
_standaloneGov.initializeGame({
|
|
132
|
+
gameId: gameId, attestationStartTime: block.timestamp, attestationGracePeriod: 2 days
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Second initialization for the same gameId should revert.
|
|
136
|
+
vm.expectRevert(DefifaGovernor.DefifaGovernor_AlreadyInitialized.selector);
|
|
137
|
+
_standaloneGov.initializeGame({
|
|
138
|
+
gameId: gameId, attestationStartTime: block.timestamp, attestationGracePeriod: 2 days
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// =========================================================================
|
|
143
|
+
// 1b. Re-initialization blocked even through the deployer (integration)
|
|
144
|
+
// =========================================================================
|
|
145
|
+
function testRevert_initializeGame_alreadyInitialized_viaDeployer() external {
|
|
146
|
+
// Launch a game (this calls initializeGame internally).
|
|
147
|
+
_setupGame(4, 1 ether);
|
|
148
|
+
|
|
149
|
+
// The governor is now owned by the deployer. Trying to initialize the same game again
|
|
150
|
+
// via the deployer is not possible because there is no public re-init path. But we
|
|
151
|
+
// verify the packed info is non-zero, confirming the guard would trigger.
|
|
152
|
+
assertTrue(_gov.attestationStartTimeOf(_gameId) > 0 || _gov.attestationGracePeriodOf(_gameId) > 0);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// =========================================================================
|
|
156
|
+
// 2. uint48 overflow on attestationStartTime
|
|
157
|
+
// =========================================================================
|
|
158
|
+
function testRevert_initializeGame_attestationStartTimeOverflow() external {
|
|
159
|
+
DefifaGovernor _standaloneGov = new DefifaGovernor(jbController(), address(this));
|
|
160
|
+
|
|
161
|
+
// type(uint48).max + 1 should overflow the 48-bit packing.
|
|
162
|
+
uint256 overflowStartTime = uint256(type(uint48).max) + 1;
|
|
163
|
+
|
|
164
|
+
vm.expectRevert(DefifaGovernor.DefifaGovernor_Uint48Overflow.selector);
|
|
165
|
+
_standaloneGov.initializeGame({
|
|
166
|
+
gameId: 99, attestationStartTime: overflowStartTime, attestationGracePeriod: 2 days
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// =========================================================================
|
|
171
|
+
// 3. uint48 overflow on attestationGracePeriod
|
|
172
|
+
// =========================================================================
|
|
173
|
+
function testRevert_initializeGame_attestationGracePeriodOverflow() external {
|
|
174
|
+
DefifaGovernor _standaloneGov = new DefifaGovernor(jbController(), address(this));
|
|
175
|
+
|
|
176
|
+
// type(uint48).max + 1 should overflow the 48-bit packing.
|
|
177
|
+
uint256 overflowGracePeriod = uint256(type(uint48).max) + 1;
|
|
178
|
+
|
|
179
|
+
vm.expectRevert(DefifaGovernor.DefifaGovernor_Uint48Overflow.selector);
|
|
180
|
+
_standaloneGov.initializeGame({
|
|
181
|
+
gameId: 100, attestationStartTime: block.timestamp, attestationGracePeriod: overflowGracePeriod
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// =========================================================================
|
|
186
|
+
// 4. DefifaHook_DelegateAddressZero in setTierDelegateTo
|
|
187
|
+
// =========================================================================
|
|
188
|
+
function testRevert_setTierDelegateTo_zeroAddress() external {
|
|
189
|
+
_setupGame(4, 1 ether);
|
|
190
|
+
|
|
191
|
+
// _users[0] owns an NFT in tier 1 during the MINT phase.
|
|
192
|
+
vm.prank(_users[0]);
|
|
193
|
+
vm.expectRevert(DefifaHook.DefifaHook_DelegateAddressZero.selector);
|
|
194
|
+
_nft.setTierDelegateTo({delegatee: address(0), tierId: 1});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// =========================================================================
|
|
198
|
+
// 5. DefifaHook_DelegateAddressZero in setTierDelegatesTo (batch)
|
|
199
|
+
// =========================================================================
|
|
200
|
+
function testRevert_setTierDelegatesTo_zeroAddress() external {
|
|
201
|
+
_setupGame(4, 1 ether);
|
|
202
|
+
|
|
203
|
+
DefifaDelegation[] memory delegations = new DefifaDelegation[](1);
|
|
204
|
+
delegations[0] = DefifaDelegation({delegatee: address(0), tierId: 1});
|
|
205
|
+
|
|
206
|
+
vm.prank(_users[0]);
|
|
207
|
+
vm.expectRevert(DefifaHook.DefifaHook_DelegateAddressZero.selector);
|
|
208
|
+
_nft.setTierDelegatesTo(delegations);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// =========================================================================
|
|
212
|
+
// 5b. Batch delegation reverts on address(0) even in second element
|
|
213
|
+
// =========================================================================
|
|
214
|
+
function testRevert_setTierDelegatesTo_zeroAddress_secondElement() external {
|
|
215
|
+
_setupGame(4, 1 ether);
|
|
216
|
+
|
|
217
|
+
// First delegation is valid, second has address(0).
|
|
218
|
+
DefifaDelegation[] memory delegations = new DefifaDelegation[](2);
|
|
219
|
+
delegations[0] = DefifaDelegation({delegatee: _users[0], tierId: 1});
|
|
220
|
+
delegations[1] = DefifaDelegation({delegatee: address(0), tierId: 2});
|
|
221
|
+
|
|
222
|
+
vm.prank(_users[0]);
|
|
223
|
+
vm.expectRevert(DefifaHook.DefifaHook_DelegateAddressZero.selector);
|
|
224
|
+
_nft.setTierDelegatesTo(delegations);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// =========================================================================
|
|
228
|
+
// SETUP HELPERS (adapted from DefifaSecurity.t.sol)
|
|
229
|
+
// =========================================================================
|
|
230
|
+
|
|
231
|
+
function _setupGame(uint8 nTiers, uint256 tierPrice) internal {
|
|
232
|
+
DefifaLaunchProjectData memory d = _launchData(nTiers, tierPrice);
|
|
233
|
+
(_pid, _nft, _gov) = _launch(d);
|
|
234
|
+
vm.warp(d.start - d.mintPeriodDuration - d.refundPeriodDuration);
|
|
235
|
+
_users = new address[](nTiers);
|
|
236
|
+
for (uint256 i; i < nTiers; i++) {
|
|
237
|
+
_users[i] = _addr(i);
|
|
238
|
+
_mint(_users[i], i + 1, tierPrice);
|
|
239
|
+
vm.warp(block.timestamp + 1);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function _launchData(uint8 n, uint256 tierPrice) internal returns (DefifaLaunchProjectData memory) {
|
|
244
|
+
DefifaTierParams[] memory tp = new DefifaTierParams[](n);
|
|
245
|
+
for (uint256 i; i < n; i++) {
|
|
246
|
+
tp[i] = DefifaTierParams({
|
|
247
|
+
reservedRate: 1001,
|
|
248
|
+
reservedTokenBeneficiary: address(0),
|
|
249
|
+
encodedIPFSUri: bytes32(0),
|
|
250
|
+
shouldUseReservedTokenBeneficiaryAsDefault: false,
|
|
251
|
+
name: "DEFIFA"
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
return DefifaLaunchProjectData({
|
|
255
|
+
name: "DEFIFA",
|
|
256
|
+
projectUri: "",
|
|
257
|
+
contractUri: "",
|
|
258
|
+
baseUri: "",
|
|
259
|
+
token: JBAccountingContext({token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: JBCurrencyIds.ETH}),
|
|
260
|
+
mintPeriodDuration: 1 days,
|
|
261
|
+
start: uint48(block.timestamp + 3 days),
|
|
262
|
+
refundPeriodDuration: 1 days,
|
|
263
|
+
store: new JB721TiersHookStore(),
|
|
264
|
+
splits: new JBSplit[](0),
|
|
265
|
+
attestationStartTime: 0,
|
|
266
|
+
attestationGracePeriod: 100_381,
|
|
267
|
+
defaultAttestationDelegate: address(0),
|
|
268
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
269
|
+
tierPrice: uint104(tierPrice),
|
|
270
|
+
tiers: tp,
|
|
271
|
+
defaultTokenUriResolver: IJB721TokenUriResolver(address(0)),
|
|
272
|
+
terminal: jbMultiTerminal(),
|
|
273
|
+
minParticipation: 0,
|
|
274
|
+
scorecardTimeout: 0
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function _launch(DefifaLaunchProjectData memory d) internal returns (uint256 p, DefifaHook n, DefifaGovernor g) {
|
|
279
|
+
g = governor;
|
|
280
|
+
p = deployer.launchGameWith(d);
|
|
281
|
+
JBRuleset memory fc = jbRulesets().currentOf(p);
|
|
282
|
+
if (fc.dataHook() == address(0)) (fc,) = jbRulesets().latestQueuedOf(p);
|
|
283
|
+
n = DefifaHook(fc.dataHook());
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function _addr(uint256 i) internal pure returns (address) {
|
|
287
|
+
return address(bytes20(keccak256(abi.encode("su", i))));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function _mint(address user, uint256 tid, uint256 amt) internal {
|
|
291
|
+
vm.deal(user, amt);
|
|
292
|
+
uint16[] memory m = new uint16[](1);
|
|
293
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
294
|
+
m[0] = uint16(tid);
|
|
295
|
+
bytes[] memory data = new bytes[](1);
|
|
296
|
+
data[0] = abi.encode(user, m);
|
|
297
|
+
bytes4[] memory ids = new bytes4[](1);
|
|
298
|
+
ids[0] = metadataHelper().getId("pay", address(hook));
|
|
299
|
+
vm.prank(user);
|
|
300
|
+
jbMultiTerminal().pay{value: amt}(
|
|
301
|
+
_pid, JBConstants.NATIVE_TOKEN, amt, user, 0, "", metadataHelper().createMetadata(ids, data)
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
@@ -1,21 +1,38 @@
|
|
|
1
1
|
// SPDX-License-Identifier: UNLICENSED
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
|
-
import "
|
|
5
|
-
import "../src/
|
|
6
|
-
import "../src/
|
|
7
|
-
import "../src/
|
|
8
|
-
import "
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {JBMetadataResolver} from "@bananapus/core-v6/src/libraries/JBMetadataResolver.sol";
|
|
12
|
-
import {MetadataResolverHelper} from "@bananapus/core-v6/test/helpers/MetadataResolverHelper.sol";
|
|
13
|
-
import "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
|
|
4
|
+
import {DefifaGovernor} from "../src/DefifaGovernor.sol";
|
|
5
|
+
import {DefifaDeployer} from "../src/DefifaDeployer.sol";
|
|
6
|
+
import {DefifaHook} from "../src/DefifaHook.sol";
|
|
7
|
+
import {DefifaTokenUriResolver} from "../src/DefifaTokenUriResolver.sol";
|
|
8
|
+
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
9
|
+
|
|
10
|
+
import {TestBaseWorkflow} from "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
|
|
14
11
|
import {JBTest} from "@bananapus/core-v6/test/helpers/JBTest.sol";
|
|
15
|
-
import "@bananapus/core-v6/src/libraries/JBRulesetMetadataResolver.sol";
|
|
16
|
-
import "@bananapus/
|
|
17
|
-
|
|
12
|
+
import {JBRulesetMetadataResolver} from "@bananapus/core-v6/src/libraries/JBRulesetMetadataResolver.sol";
|
|
13
|
+
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
14
|
+
|
|
15
|
+
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
18
16
|
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
17
|
+
import {DefifaLaunchProjectData} from "../src/structs/DefifaLaunchProjectData.sol";
|
|
18
|
+
import {DefifaTierParams} from "../src/structs/DefifaTierParams.sol";
|
|
19
|
+
import {DefifaTierCashOutWeight} from "../src/structs/DefifaTierCashOutWeight.sol";
|
|
20
|
+
import {DefifaDelegation} from "../src/structs/DefifaDelegation.sol";
|
|
21
|
+
import {IJBSplitHook} from "@bananapus/core-v6/src/interfaces/IJBSplitHook.sol";
|
|
22
|
+
import {IJB721TokenUriResolver} from "@bananapus/721-hook-v6/src/interfaces/IJB721TokenUriResolver.sol";
|
|
23
|
+
import {IJBRulesetApprovalHook} from "@bananapus/core-v6/src/interfaces/IJBRulesets.sol";
|
|
24
|
+
import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
25
|
+
import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
26
|
+
import {JBRulesetMetadata} from "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
27
|
+
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
28
|
+
import {JBSplitGroup} from "@bananapus/core-v6/src/structs/JBSplitGroup.sol";
|
|
29
|
+
import {JBFundAccessLimitGroup} from "@bananapus/core-v6/src/structs/JBFundAccessLimitGroup.sol";
|
|
30
|
+
import {JBRulesetConfig, JBTerminalConfig} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
|
|
31
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
32
|
+
import {JBMultiTerminal} from "@bananapus/core-v6/src/JBMultiTerminal.sol";
|
|
33
|
+
import {JBPermissionsData} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
34
|
+
import {JBCurrencyIds} from "@bananapus/core-v6/src/libraries/JBCurrencyIds.sol";
|
|
35
|
+
import {ITypeface} from "lib/typeface/contracts/interfaces/ITypeface.sol";
|
|
19
36
|
|
|
20
37
|
/// @notice Tests for PR #22 (M-D8): fee accounting after removing duplicate nana fee.
|
|
21
38
|
/// Verifies that only the fee portion of the pot is sent as payouts during fulfillment,
|
|
@@ -92,10 +109,10 @@ contract DefifaFeeAccountingTest is JBTest, TestBaseWorkflow {
|
|
|
92
109
|
hook = new DefifaHook(jbDirectory(), IERC20(_defifaToken), IERC20(_nanaToken));
|
|
93
110
|
governor = new DefifaGovernor(jbController(), address(this));
|
|
94
111
|
JBAddressRegistry _registry = new JBAddressRegistry();
|
|
95
|
-
DefifaTokenUriResolver
|
|
112
|
+
DefifaTokenUriResolver _tokenUriResolver = new DefifaTokenUriResolver(ITypeface(address(0)));
|
|
96
113
|
deployer = new DefifaDeployer(
|
|
97
114
|
address(hook),
|
|
98
|
-
|
|
115
|
+
_tokenUriResolver,
|
|
99
116
|
governor,
|
|
100
117
|
jbController(),
|
|
101
118
|
_registry,
|
|
@@ -112,7 +129,10 @@ contract DefifaFeeAccountingTest is JBTest, TestBaseWorkflow {
|
|
|
112
129
|
.setPermissionsFor(
|
|
113
130
|
projectOwner,
|
|
114
131
|
JBPermissionsData({
|
|
115
|
-
operator: address(deployer),
|
|
132
|
+
operator: address(deployer),
|
|
133
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
134
|
+
projectId: uint64(_defifaProjectId),
|
|
135
|
+
permissionIds: permissionIds
|
|
116
136
|
})
|
|
117
137
|
);
|
|
118
138
|
|
|
@@ -476,6 +496,7 @@ contract DefifaFeeAccountingTest is JBTest, TestBaseWorkflow {
|
|
|
476
496
|
vm.deal(users[i], 1 ether);
|
|
477
497
|
|
|
478
498
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
499
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
479
500
|
rawMetadata[0] = uint16(i + 1);
|
|
480
501
|
bytes memory metadata = _buildPayMetadata(abi.encode(users[i], rawMetadata));
|
|
481
502
|
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: UNLICENSED
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
import "forge-std/Test.sol";
|
|
6
|
-
// solhint-disable-next-line no-unused-import
|
|
7
|
-
import "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
|
|
4
|
+
import {TestBaseWorkflow} from "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
|
|
8
5
|
|
|
9
6
|
import {DefifaGovernor} from "../src/DefifaGovernor.sol";
|
|
10
7
|
import {DefifaDeployer} from "../src/DefifaDeployer.sol";
|
|
@@ -12,13 +9,9 @@ import {DefifaHook} from "../src/DefifaHook.sol";
|
|
|
12
9
|
import {DefifaTokenUriResolver} from "../src/DefifaTokenUriResolver.sol";
|
|
13
10
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
14
11
|
|
|
15
|
-
import {JBMetadataResolver} from "@bananapus/core-v6/src/libraries/JBMetadataResolver.sol";
|
|
16
|
-
import {MetadataResolverHelper} from "@bananapus/core-v6/test/helpers/MetadataResolverHelper.sol";
|
|
17
12
|
import {JBTest} from "@bananapus/core-v6/test/helpers/JBTest.sol";
|
|
18
13
|
import {JBRulesetMetadataResolver} from "@bananapus/core-v6/src/libraries/JBRulesetMetadataResolver.sol";
|
|
19
|
-
import {
|
|
20
|
-
JB721TiersRulesetMetadataResolver
|
|
21
|
-
} from "@bananapus/721-hook-v6/src/libraries/JB721TiersRulesetMetadataResolver.sol";
|
|
14
|
+
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
22
15
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
23
16
|
|
|
24
17
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
@@ -30,6 +23,17 @@ import {DefifaDelegation} from "../src/structs/DefifaDelegation.sol";
|
|
|
30
23
|
import {DefifaLaunchProjectData} from "../src/structs/DefifaLaunchProjectData.sol";
|
|
31
24
|
import {DefifaTierParams} from "../src/structs/DefifaTierParams.sol";
|
|
32
25
|
import {DefifaTierCashOutWeight} from "../src/structs/DefifaTierCashOutWeight.sol";
|
|
26
|
+
import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
27
|
+
import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
28
|
+
import {JBCurrencyIds} from "@bananapus/core-v6/src/libraries/JBCurrencyIds.sol";
|
|
29
|
+
import {JBFundAccessLimitGroup} from "@bananapus/core-v6/src/structs/JBFundAccessLimitGroup.sol";
|
|
30
|
+
import {JBMultiTerminal} from "@bananapus/core-v6/src/JBMultiTerminal.sol";
|
|
31
|
+
import {JBRulesetConfig, JBTerminalConfig} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
|
|
32
|
+
import {JBRulesetMetadata} from "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
33
|
+
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
34
|
+
import {JBSplitGroup} from "@bananapus/core-v6/src/structs/JBSplitGroup.sol";
|
|
35
|
+
import {IJBRulesetApprovalHook} from "@bananapus/core-v6/src/interfaces/IJBRulesets.sol";
|
|
36
|
+
import {JBTerminalStore} from "@bananapus/core-v6/src/JBTerminalStore.sol";
|
|
33
37
|
|
|
34
38
|
/// @dev Helper to read block.timestamp via an external call, bypassing the via-ir optimizer's timestamp caching.
|
|
35
39
|
contract TimestampReader {
|
|
@@ -118,10 +122,10 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
118
122
|
);
|
|
119
123
|
governor = new DefifaGovernor(jbController(), address(this));
|
|
120
124
|
JBAddressRegistry _registry = new JBAddressRegistry();
|
|
121
|
-
DefifaTokenUriResolver
|
|
125
|
+
DefifaTokenUriResolver _tokenUriResolver = new DefifaTokenUriResolver(ITypeface(address(0)));
|
|
122
126
|
deployer = new DefifaDeployer(
|
|
123
127
|
address(hook),
|
|
124
|
-
|
|
128
|
+
_tokenUriResolver,
|
|
125
129
|
governor,
|
|
126
130
|
jbController(),
|
|
127
131
|
_registry,
|
|
@@ -300,6 +304,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
300
304
|
vm.deal(_users[i], 1 ether);
|
|
301
305
|
// Build metadata to buy specific NFT
|
|
302
306
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
307
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
303
308
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
304
309
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
305
310
|
// Pay to the project and mint an NFT
|
|
@@ -316,6 +321,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
316
321
|
vm.deal(_users[i], 1 ether);
|
|
317
322
|
// Build metadata to buy specific NFT
|
|
318
323
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
324
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
319
325
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
320
326
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
321
327
|
// Pay to the project and mint an NFT
|
|
@@ -399,6 +405,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
399
405
|
vm.deal(_users[i], 1 ether);
|
|
400
406
|
// Build metadata to buy specific NFT
|
|
401
407
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
408
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
402
409
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
403
410
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
404
411
|
// Pay to the project and mint an NFT
|
|
@@ -415,6 +422,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
415
422
|
vm.warp(_tsReader.timestamp() + 1);
|
|
416
423
|
assertEq(
|
|
417
424
|
_governor.MAX_ATTESTATION_POWER_TIER(),
|
|
425
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
418
426
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(_tsReader.timestamp()))
|
|
419
427
|
);
|
|
420
428
|
}
|
|
@@ -468,6 +476,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
468
476
|
bytes memory metadata;
|
|
469
477
|
{
|
|
470
478
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
479
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
471
480
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
472
481
|
metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
473
482
|
}
|
|
@@ -481,6 +490,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
481
490
|
vm.warp(block.timestamp + 1);
|
|
482
491
|
assertEq(
|
|
483
492
|
_governor.MAX_ATTESTATION_POWER_TIER(),
|
|
493
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
484
494
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(block.timestamp))
|
|
485
495
|
);
|
|
486
496
|
// Have a user mint and refund the tier
|
|
@@ -548,8 +558,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
548
558
|
)
|
|
549
559
|
internal
|
|
550
560
|
{
|
|
551
|
-
uint256 _pot = jbMultiTerminal()
|
|
552
|
-
.currentSurplusOf(_projectId, jbMultiTerminal().accountingContextsOf(_projectId), 18, JBCurrencyIds.ETH);
|
|
561
|
+
uint256 _pot = jbMultiTerminal().currentSurplusOf(_projectId, new address[](0), 18, JBCurrencyIds.ETH);
|
|
553
562
|
// Assert that the deployer did *NOT* receive any fee tokens.
|
|
554
563
|
assertEq(IERC20(_protocolFeeProjectTokenAccount).balanceOf(address(deployer)), 0);
|
|
555
564
|
assertEq(IERC20(_defifaProjectTokenAccount).balanceOf(address(deployer)), 0);
|
|
@@ -559,8 +568,8 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
559
568
|
_verifySingleCashOut(_projectId, _nft, scorecards[i], _users[i], _pot, _sumDistribution, distribution, i);
|
|
560
569
|
}
|
|
561
570
|
// All NFTs should have been redeemed, only some dust should be left
|
|
562
|
-
uint256 remainingSurplus =
|
|
563
|
-
.currentSurplusOf(_projectId,
|
|
571
|
+
uint256 remainingSurplus =
|
|
572
|
+
jbMultiTerminal().currentSurplusOf(_projectId, new address[](0), 18, JBCurrencyIds.ETH);
|
|
564
573
|
uint256 _expected = _pot * (_nft.TOTAL_CASHOUT_WEIGHT() - assignedCashOutWeight) / _nft.TOTAL_CASHOUT_WEIGHT();
|
|
565
574
|
assertApproxEqAbs(remainingSurplus, _expected, 10 ** 14);
|
|
566
575
|
|
|
@@ -621,6 +630,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
621
630
|
|
|
622
631
|
function testVotingPowerDecreasesAfterRefund() public {
|
|
623
632
|
uint256 nOfOtherTiers = 31;
|
|
633
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
624
634
|
DefifaLaunchProjectData memory defifaData = getBasicDefifaLaunchData(uint8(nOfOtherTiers + 1));
|
|
625
635
|
(uint256 _projectId, DefifaHook _hook, DefifaGovernor _governor) = createDefifaProject(defifaData);
|
|
626
636
|
|
|
@@ -697,6 +707,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
697
707
|
vm.assume(totalWeight > 1);
|
|
698
708
|
|
|
699
709
|
address[] memory _users = new address[](nOfOtherTiers + nUsersWithWinningTier);
|
|
710
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
700
711
|
DefifaLaunchProjectData memory defifaData = getBasicDefifaLaunchData(uint8(nOfOtherTiers + 1));
|
|
701
712
|
(uint256 _projectId, DefifaHook _nft, DefifaGovernor _governor) = createDefifaProject(defifaData);
|
|
702
713
|
// Phase 1: minting
|
|
@@ -711,6 +722,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
711
722
|
if (i < nOfOtherTiers) {
|
|
712
723
|
// Build metadata to buy specific NFT
|
|
713
724
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
725
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
714
726
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
715
727
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
716
728
|
// Pay to the project and mint an NFT
|
|
@@ -722,11 +734,13 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
722
734
|
vm.warp(block.timestamp + 1);
|
|
723
735
|
assertEq(
|
|
724
736
|
_governor.MAX_ATTESTATION_POWER_TIER(),
|
|
737
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
725
738
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(block.timestamp))
|
|
726
739
|
);
|
|
727
740
|
} else {
|
|
728
741
|
// Build metadata to buy specific NFT
|
|
729
742
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
743
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
730
744
|
rawMetadata[0] = uint16(nOfOtherTiers + 1); // reward tier, 1 indexed
|
|
731
745
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
732
746
|
// Pay to the project and mint an NFT
|
|
@@ -738,6 +752,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
738
752
|
vm.warp(block.timestamp + 1);
|
|
739
753
|
assertEq(
|
|
740
754
|
_governor.MAX_ATTESTATION_POWER_TIER() / (i - nOfOtherTiers + 1),
|
|
755
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
741
756
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(block.timestamp))
|
|
742
757
|
);
|
|
743
758
|
}
|
|
@@ -764,6 +779,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
764
779
|
vm.assume(totalWeight > 1);
|
|
765
780
|
|
|
766
781
|
address[] memory _users = new address[](nOfOtherTiers + nUsersWithWinningTier);
|
|
782
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
767
783
|
DefifaLaunchProjectData memory defifaData = getBasicDefifaLaunchData(uint8(nOfOtherTiers + 1));
|
|
768
784
|
(uint256 _projectId, DefifaHook _nft, DefifaGovernor _governor) = createDefifaProject(defifaData);
|
|
769
785
|
// Phase 1: minting
|
|
@@ -778,6 +794,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
778
794
|
if (i < nOfOtherTiers) {
|
|
779
795
|
// Build metadata to buy specific NFT
|
|
780
796
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
797
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
781
798
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
782
799
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
783
800
|
// Pay to the project and mint an NFT
|
|
@@ -789,11 +806,13 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
789
806
|
vm.warp(block.timestamp + 1);
|
|
790
807
|
assertEq(
|
|
791
808
|
_governor.MAX_ATTESTATION_POWER_TIER(),
|
|
809
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
792
810
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(block.timestamp))
|
|
793
811
|
);
|
|
794
812
|
} else {
|
|
795
813
|
// Build metadata to buy specific NFT
|
|
796
814
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
815
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
797
816
|
rawMetadata[0] = uint16(nOfOtherTiers + 1); // reward tier, 1 indexed
|
|
798
817
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
799
818
|
// Pay to the project and mint an NFT
|
|
@@ -805,6 +824,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
805
824
|
vm.warp(block.timestamp + 1);
|
|
806
825
|
assertEq(
|
|
807
826
|
_governor.MAX_ATTESTATION_POWER_TIER() / (i - nOfOtherTiers + 1),
|
|
827
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
808
828
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(block.timestamp))
|
|
809
829
|
);
|
|
810
830
|
}
|
|
@@ -863,8 +883,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
863
883
|
_governor.ratifyScorecardFrom(_gameId, scorecards);
|
|
864
884
|
vm.warp(block.timestamp + 1);
|
|
865
885
|
|
|
866
|
-
uint256 _pot = jbMultiTerminal()
|
|
867
|
-
.currentSurplusOf(_projectId, jbMultiTerminal().accountingContextsOf(_projectId), 18, JBCurrencyIds.ETH);
|
|
886
|
+
uint256 _pot = jbMultiTerminal().currentSurplusOf(_projectId, new address[](0), 18, JBCurrencyIds.ETH);
|
|
868
887
|
|
|
869
888
|
// Verify that the cashOutWeights actually changed
|
|
870
889
|
for (uint256 i = 0; i < _users.length; i++) {
|
|
@@ -911,8 +930,8 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
911
930
|
}
|
|
912
931
|
// All NFTs should have been redeemed, only some dust should be left
|
|
913
932
|
// Max allowed dust is 0.0001
|
|
914
|
-
uint256 remainingSurplus =
|
|
915
|
-
.currentSurplusOf(_projectId,
|
|
933
|
+
uint256 remainingSurplus =
|
|
934
|
+
jbMultiTerminal().currentSurplusOf(_projectId, new address[](0), 18, JBCurrencyIds.ETH);
|
|
916
935
|
assertApproxEqAbs(
|
|
917
936
|
remainingSurplus, _pot * (totalCashOutWeight - assignedCashOutWeight) / totalCashOutWeight, 10 ** 14
|
|
918
937
|
);
|
|
@@ -1061,6 +1080,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1061
1080
|
vm.deal(_users[i], 1 ether);
|
|
1062
1081
|
// Build metadata to buy specific NFT
|
|
1063
1082
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
1083
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1064
1084
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
1065
1085
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
1066
1086
|
// Pay to the project and mint an NFT
|
|
@@ -1077,6 +1097,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1077
1097
|
vm.warp(_tsReader.timestamp() + 1);
|
|
1078
1098
|
assertEq(
|
|
1079
1099
|
_governor.MAX_ATTESTATION_POWER_TIER(),
|
|
1100
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1080
1101
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(_tsReader.timestamp()))
|
|
1081
1102
|
);
|
|
1082
1103
|
}
|
|
@@ -1124,6 +1145,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1124
1145
|
vm.deal(_users[i], 1 ether);
|
|
1125
1146
|
// Build metadata to buy specific NFT
|
|
1126
1147
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
1148
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1127
1149
|
rawMetadata[0] = uint16(i + 1); // reward tier, 1 indexed
|
|
1128
1150
|
bytes memory metadata = _buildPayMetadata(abi.encode(_users[i], rawMetadata));
|
|
1129
1151
|
// Pay to the project and mint an NFT
|
|
@@ -1139,6 +1161,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1139
1161
|
// Forward 1 block, user should receive all the voting power of the tier, as its the only NFT
|
|
1140
1162
|
assertEq(
|
|
1141
1163
|
_governor.MAX_ATTESTATION_POWER_TIER(),
|
|
1164
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1142
1165
|
_governor.getAttestationWeight(_gameId, _users[i], uint48(block.timestamp))
|
|
1143
1166
|
);
|
|
1144
1167
|
}
|
|
@@ -1241,6 +1264,7 @@ contract DefifaGovernorTest is JBTest, TestBaseWorkflow {
|
|
|
1241
1264
|
assertEq(_hook.balanceOf(_refundUser), 0);
|
|
1242
1265
|
// Build metadata to buy specific NFT
|
|
1243
1266
|
uint16[] memory rawMetadata = new uint16[](1);
|
|
1267
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1244
1268
|
rawMetadata[0] = uint16(_tierId); // reward tier, 1 indexed
|
|
1245
1269
|
bytes memory metadata = _buildPayMetadata(abi.encode(_refundUser, rawMetadata));
|
|
1246
1270
|
// Pay to the project and mint an NFT
|