@bananapus/core-v6 0.0.21 → 0.0.22
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 +0 -1
- package/AUDIT_INSTRUCTIONS.md +1 -1
- package/CHANGE_LOG.md +3 -3
- package/RISKS.md +3 -3
- package/SKILLS.md +8 -8
- package/USER_JOURNEYS.md +1 -1
- package/foundry.toml +0 -1
- package/package.json +1 -1
- package/src/JBMultiTerminal.sol +92 -192
- package/src/JBTerminalStore.sol +405 -235
- package/src/interfaces/IJBMultiTerminal.sol +0 -4
- package/src/interfaces/IJBTerminal.sol +4 -4
- package/src/interfaces/IJBTerminalStore.sol +65 -33
- package/src/libraries/JBPayoutSplitGroupLib.sol +0 -1
- package/src/libraries/JBSurplus.sol +3 -4
- package/test/ComprehensiveInvariant.t.sol +5 -7
- package/test/CoreExploitTests.t.sol +18 -23
- package/test/TestCashOut.sol +6 -6
- package/test/TestMultiTerminalSurplus.sol +4 -4
- package/test/TestMultiTokenSurplus.sol +6 -23
- package/test/TestTerminalMigration.sol +2 -7
- package/test/fork/TestSequencerPriceFeedFork.sol +1 -1
- package/test/fork/TestTerminalPreviewParityFork.sol +0 -1
- package/test/invariants/TerminalStoreInvariant.t.sol +5 -7
- package/test/units/static/JBMultiTerminal/JBMultiTerminalSetup.sol +1 -2
- package/test/units/static/JBMultiTerminal/TestAccountingContextsOf.sol +23 -24
- package/test/units/static/JBMultiTerminal/TestAddAccountingContextsFor.sol +79 -119
- package/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol +33 -26
- package/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol +32 -27
- package/test/units/static/JBMultiTerminal/TestExecutePayout.sol +22 -4
- package/test/units/static/JBMultiTerminal/TestExecuteProcessFee.sol +8 -5
- package/test/units/static/JBMultiTerminal/TestPay.sol +41 -33
- package/test/units/static/JBMultiTerminal/TestPreviewCashOutFrom.sol +19 -18
- package/test/units/static/JBMultiTerminal/TestPreviewPayFor.sol +38 -22
- package/test/units/static/JBMultiTerminal/TestProcessHeldFeesOf.sol +9 -6
- package/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol +4 -4
- package/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol +37 -32
- package/test/units/static/JBSurplus/TestSurplusFuzz.sol +5 -20
- package/test/units/static/JBTerminalStore/JBTerminalStoreSetup.sol +17 -0
- package/test/units/static/JBTerminalStore/TestCurrentReclaimableSurplusOf.sol +120 -246
- package/test/units/static/JBTerminalStore/TestCurrentSurplusOf.sol +29 -7
- package/test/units/static/JBTerminalStore/TestCurrentTotalSurplusOf.sol +88 -20
- package/test/units/static/JBTerminalStore/TestPreviewCashOutFrom.sol +30 -29
- package/test/units/static/JBTerminalStore/TestPreviewPayFrom.sol +46 -16
- package/test/units/static/JBTerminalStore/TestRecordCashOutsFor.sol +24 -53
- package/test/units/static/JBTerminalStore/TestRecordPayoutFor.sol +24 -4
- package/test/units/static/JBTerminalStore/TestRecordUsedAllowanceOf.sol +14 -4
- package/test/units/static/JBTerminalStore/TestUint224Overflow.sol +21 -3
|
@@ -37,31 +37,26 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
37
37
|
super.terminalStoreSetup();
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
/// @notice Helper to register an accounting context with the store (pranks as the terminal).
|
|
41
|
+
function _registerContext(JBAccountingContext memory ctx) internal {
|
|
42
|
+
JBAccountingContext[] memory ctxs = new JBAccountingContext[](1);
|
|
43
|
+
ctxs[0] = ctx;
|
|
44
|
+
vm.prank(address(_terminal));
|
|
45
|
+
_store.recordAccountingContextOf(_projectId, ctxs);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// @notice Helper to set balance for the terminal/project/token via vm.store.
|
|
49
|
+
function _setBalance(uint256 balance) internal {
|
|
42
50
|
bytes32 balanceOfSlot = keccak256(abi.encode(address(_terminal), uint256(0)));
|
|
43
51
|
bytes32 projectSlot = keccak256(abi.encode(_projectId, uint256(balanceOfSlot)));
|
|
44
52
|
bytes32 slot = keccak256(abi.encode(address(_token), uint256(projectSlot)));
|
|
45
|
-
|
|
46
|
-
bytes32 balanceBytes = bytes32(_balance);
|
|
47
|
-
|
|
48
|
-
// Set balance
|
|
49
|
-
vm.store(address(_store), slot, balanceBytes);
|
|
50
|
-
|
|
51
|
-
// Ensure balance is set correctly
|
|
52
|
-
uint256 _balanceCallReturn = _store.balanceOf(address(_terminal), _projectId, address(_token));
|
|
53
|
-
assertEq(_balanceCallReturn, _balance);
|
|
54
|
-
_;
|
|
53
|
+
vm.store(address(_store), slot, bytes32(balance));
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
JBAccountingContext[] memory _contexts = new JBAccountingContext[](1);
|
|
62
|
-
_contexts[0] = JBAccountingContext({token: address(_token), decimals: 18, currency: _currency});
|
|
63
|
-
|
|
64
|
-
// JBRulesets return calldata
|
|
56
|
+
/// @notice Helper to set up common mocks for surplus computation.
|
|
57
|
+
/// @param packedMetadata The packed ruleset metadata.
|
|
58
|
+
/// @param payoutLimits The payout limits to mock.
|
|
59
|
+
function _mockSurplusInfra(uint256 packedMetadata, JBCurrencyAmount[] memory payoutLimits) internal {
|
|
65
60
|
JBRuleset memory _returnedRuleset = JBRuleset({
|
|
66
61
|
cycleNumber: uint48(block.timestamp),
|
|
67
62
|
id: uint48(block.timestamp),
|
|
@@ -71,32 +66,45 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
71
66
|
weight: 1e18,
|
|
72
67
|
weightCutPercent: 0,
|
|
73
68
|
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
74
|
-
metadata:
|
|
69
|
+
metadata: packedMetadata
|
|
75
70
|
});
|
|
76
71
|
|
|
77
|
-
// mock call to JBRulesets currentOf
|
|
78
72
|
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(_returnedRuleset));
|
|
79
|
-
|
|
80
|
-
// mock current surplus as zero
|
|
73
|
+
mockExpect(address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(_controller));
|
|
81
74
|
mockExpect(
|
|
82
|
-
address(
|
|
83
|
-
abi.encodeCall(IJBTerminal.currentSurplusOf, (_projectId, _contexts, 18, _currency)),
|
|
84
|
-
abi.encode(0)
|
|
75
|
+
address(_controller), abi.encodeCall(IJBController.FUND_ACCESS_LIMITS, ()), abi.encode(_accessLimits)
|
|
85
76
|
);
|
|
77
|
+
mockExpect(
|
|
78
|
+
address(_accessLimits),
|
|
79
|
+
abi.encodeCall(
|
|
80
|
+
IJBFundAccessLimits.payoutLimitsOf, (_projectId, block.timestamp, address(_terminal), address(_token))
|
|
81
|
+
),
|
|
82
|
+
abi.encode(payoutLimits)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function test_GivenCurrentSurplusEqZero() external {
|
|
87
|
+
// it will return zero
|
|
88
|
+
|
|
89
|
+
// Register accounting context so the store can resolve it.
|
|
90
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
91
|
+
|
|
92
|
+
// No balance set — surplus is 0.
|
|
93
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
94
|
+
_mockSurplusInfra(0, _emptyLimits);
|
|
86
95
|
|
|
87
96
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
88
97
|
_terminals[0] = _terminal;
|
|
89
98
|
uint256 reclaimable =
|
|
90
|
-
_store.currentReclaimableSurplusOf(_projectId, _tokenCount, _terminals,
|
|
99
|
+
_store.currentReclaimableSurplusOf(_projectId, _tokenCount, _terminals, new address[](0), 18, _currency);
|
|
91
100
|
assertEq(0, reclaimable);
|
|
92
101
|
}
|
|
93
102
|
|
|
94
|
-
function test_GivenCurrentSurplusGtZero() external
|
|
103
|
+
function test_GivenCurrentSurplusGtZero() external {
|
|
95
104
|
// it will get the number of outstanding tokens and return the reclaimable surplus
|
|
96
105
|
|
|
97
|
-
//
|
|
98
|
-
JBAccountingContext
|
|
99
|
-
_contexts[0] = JBAccountingContext({token: address(_token), decimals: 18, currency: _currency});
|
|
106
|
+
// Register accounting context.
|
|
107
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
100
108
|
|
|
101
109
|
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
102
110
|
reservedPercent: 0,
|
|
@@ -122,36 +130,18 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
122
130
|
|
|
123
131
|
uint256 _packedMetadata = JBRulesetMetadataResolver.packRulesetMetadata(_metadata);
|
|
124
132
|
|
|
125
|
-
// JBRulesets return calldata
|
|
126
|
-
JBRuleset memory _returnedRuleset = JBRuleset({
|
|
127
|
-
cycleNumber: uint48(block.timestamp),
|
|
128
|
-
id: uint48(block.timestamp),
|
|
129
|
-
basedOnId: 0,
|
|
130
|
-
start: uint48(block.timestamp),
|
|
131
|
-
duration: uint32(block.timestamp + 1000),
|
|
132
|
-
weight: 1e18,
|
|
133
|
-
weightCutPercent: 0,
|
|
134
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
135
|
-
metadata: _packedMetadata
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// mock call to JBRulesets currentOf
|
|
139
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(_returnedRuleset));
|
|
140
|
-
|
|
141
|
-
// mock call to JBDirectory controllerOf
|
|
142
|
-
mockExpect(address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(_controller));
|
|
143
|
-
|
|
144
|
-
// "mock" payout amount since the currentSurplusOf call is mocked
|
|
145
133
|
uint224 _payout = 1e17;
|
|
146
134
|
uint256 _supply = 1e19;
|
|
147
135
|
uint256 _cashoutAmount = 1e18;
|
|
136
|
+
uint256 _surplus = _supply - _payout;
|
|
148
137
|
|
|
149
|
-
// surplus
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
);
|
|
138
|
+
// Set balance = surplus + payout limit to get the desired surplus after deducting limits.
|
|
139
|
+
// balance - payoutLimit = surplus => balance = surplus + payoutLimit
|
|
140
|
+
// But we want surplus = _supply - _payout = 9.9e18. So set balance = surplus (with zero limits).
|
|
141
|
+
_setBalance(_surplus);
|
|
142
|
+
|
|
143
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
144
|
+
_mockSurplusInfra(_packedMetadata, _emptyLimits);
|
|
155
145
|
|
|
156
146
|
// mock JBController totalTokenSupplyWithReservedTokensOf
|
|
157
147
|
mockExpect(
|
|
@@ -163,21 +153,20 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
163
153
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
164
154
|
_terminals[0] = _terminal;
|
|
165
155
|
uint256 reclaimable =
|
|
166
|
-
_store.currentReclaimableSurplusOf(_projectId, _cashoutAmount, _terminals,
|
|
156
|
+
_store.currentReclaimableSurplusOf(_projectId, _cashoutAmount, _terminals, new address[](0), 18, _currency);
|
|
167
157
|
|
|
168
158
|
// The above call should be calculating the reclaimable amount as we are here, so they will be congruent.
|
|
169
159
|
uint256 assumed =
|
|
170
|
-
JBCashOuts.cashOutFrom(
|
|
160
|
+
JBCashOuts.cashOutFrom(_surplus, _cashoutAmount, _supply, JBConstants.MAX_CASH_OUT_TAX_RATE / 2);
|
|
171
161
|
|
|
172
162
|
assertEq(assumed, reclaimable);
|
|
173
163
|
}
|
|
174
164
|
|
|
175
|
-
function test_GivenTokenCountIsEqToTotalSupply() external
|
|
165
|
+
function test_GivenTokenCountIsEqToTotalSupply() external {
|
|
176
166
|
// it will return the rest of the surplus
|
|
177
167
|
|
|
178
|
-
//
|
|
179
|
-
JBAccountingContext
|
|
180
|
-
_contexts[0] = JBAccountingContext({token: address(_token), decimals: 18, currency: _currency});
|
|
168
|
+
// Register accounting context.
|
|
169
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
181
170
|
|
|
182
171
|
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
183
172
|
reservedPercent: 0,
|
|
@@ -203,53 +192,34 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
203
192
|
|
|
204
193
|
uint256 _packedMetadata = JBRulesetMetadataResolver.packRulesetMetadata(_metadata);
|
|
205
194
|
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
cycleNumber: uint48(block.timestamp),
|
|
209
|
-
id: uint48(block.timestamp),
|
|
210
|
-
basedOnId: 0,
|
|
211
|
-
start: uint48(block.timestamp),
|
|
212
|
-
duration: uint32(block.timestamp + 1000),
|
|
213
|
-
weight: 1e18,
|
|
214
|
-
weightCutPercent: 0,
|
|
215
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
216
|
-
metadata: _packedMetadata
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// mock call to JBRulesets currentOf
|
|
220
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(_returnedRuleset));
|
|
195
|
+
// Set balance = tokenCount so surplus = tokenCount (with zero payout limits).
|
|
196
|
+
_setBalance(_tokenCount);
|
|
221
197
|
|
|
222
|
-
|
|
223
|
-
|
|
198
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
199
|
+
_mockSurplusInfra(_packedMetadata, _emptyLimits);
|
|
224
200
|
|
|
225
|
-
// mock
|
|
201
|
+
// mock JBController totalTokenSupplyWithReservedTokensOf
|
|
226
202
|
mockExpect(
|
|
227
|
-
address(
|
|
228
|
-
abi.encodeCall(
|
|
203
|
+
address(_controller),
|
|
204
|
+
abi.encodeCall(IJBController.totalTokenSupplyWithReservedTokensOf, (_projectId)),
|
|
229
205
|
abi.encode(_tokenCount)
|
|
230
206
|
);
|
|
231
207
|
|
|
232
|
-
// mock JBController totalTokenSupplyWithReservedTokensOf
|
|
233
|
-
bytes memory _totalTokenCall = abi.encodeCall(IJBController.totalTokenSupplyWithReservedTokensOf, (_projectId));
|
|
234
|
-
bytes memory _tokenTotal = abi.encode(_tokenCount);
|
|
235
|
-
mockExpect(address(_controller), _totalTokenCall, _tokenTotal);
|
|
236
|
-
|
|
237
208
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
238
209
|
_terminals[0] = _terminal;
|
|
239
210
|
uint256 reclaimable =
|
|
240
|
-
_store.currentReclaimableSurplusOf(_projectId, _tokenCount, _terminals,
|
|
211
|
+
_store.currentReclaimableSurplusOf(_projectId, _tokenCount, _terminals, new address[](0), 18, _currency);
|
|
241
212
|
|
|
242
213
|
// The tokenCount is equal to the total supply, so the reclaimable amount will be the same as the supply. We
|
|
243
214
|
// couldn't reclaim more.
|
|
244
215
|
assertEq(_tokenCount, reclaimable);
|
|
245
216
|
}
|
|
246
217
|
|
|
247
|
-
function test_GivenCashOutTaxRateEqZero() external
|
|
248
|
-
// it will return zero
|
|
218
|
+
function test_GivenCashOutTaxRateEqZero() external {
|
|
219
|
+
// it will return zero (cashOutTaxRate = MAX means no surplus can be reclaimed)
|
|
249
220
|
|
|
250
|
-
//
|
|
251
|
-
JBAccountingContext
|
|
252
|
-
_contexts[0] = JBAccountingContext({token: address(_token), decimals: 18, currency: _currency});
|
|
221
|
+
// Register accounting context.
|
|
222
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
253
223
|
|
|
254
224
|
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
255
225
|
reservedPercent: 0,
|
|
@@ -275,55 +245,33 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
275
245
|
|
|
276
246
|
uint256 _packedMetadata = JBRulesetMetadataResolver.packRulesetMetadata(_metadata);
|
|
277
247
|
|
|
278
|
-
//
|
|
279
|
-
|
|
280
|
-
cycleNumber: uint48(block.timestamp),
|
|
281
|
-
id: uint48(block.timestamp),
|
|
282
|
-
basedOnId: 0,
|
|
283
|
-
start: uint48(block.timestamp),
|
|
284
|
-
duration: uint32(block.timestamp + 1000),
|
|
285
|
-
weight: 1e18,
|
|
286
|
-
weightCutPercent: 0,
|
|
287
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
288
|
-
metadata: _packedMetadata
|
|
289
|
-
});
|
|
248
|
+
// Set balance = 1e18 so surplus = 1e18 (with zero payout limits).
|
|
249
|
+
_setBalance(1e18);
|
|
290
250
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
// mock call to JBDirectory controllerOf
|
|
295
|
-
mockExpect(address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(_controller));
|
|
296
|
-
|
|
297
|
-
JBCurrencyAmount[] memory _limits = new JBCurrencyAmount[](1);
|
|
298
|
-
_limits[0] = JBCurrencyAmount({amount: 0, currency: _currency});
|
|
251
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
252
|
+
_mockSurplusInfra(_packedMetadata, _emptyLimits);
|
|
299
253
|
|
|
300
254
|
// mock JBController totalTokenSupplyWithReservedTokensOf
|
|
301
|
-
bytes memory _totalTokenCall = abi.encodeCall(IJBController.totalTokenSupplyWithReservedTokensOf, (_projectId));
|
|
302
|
-
bytes memory _tokenTotal = abi.encode(1e18);
|
|
303
|
-
mockExpect(address(_controller), _totalTokenCall, _tokenTotal);
|
|
304
|
-
|
|
305
|
-
// mock current surplus
|
|
306
255
|
mockExpect(
|
|
307
|
-
address(
|
|
308
|
-
abi.encodeCall(
|
|
256
|
+
address(_controller),
|
|
257
|
+
abi.encodeCall(IJBController.totalTokenSupplyWithReservedTokensOf, (_projectId)),
|
|
309
258
|
abi.encode(1e18)
|
|
310
259
|
);
|
|
311
260
|
|
|
312
261
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
313
262
|
_terminals[0] = _terminal;
|
|
314
263
|
uint256 reclaimable =
|
|
315
|
-
_store.currentReclaimableSurplusOf(_projectId, _tokenCount, _terminals,
|
|
264
|
+
_store.currentReclaimableSurplusOf(_projectId, _tokenCount, _terminals, new address[](0), 18, _currency);
|
|
316
265
|
|
|
317
266
|
// No surplus can be reclaimed.
|
|
318
267
|
assertEq(0, reclaimable);
|
|
319
268
|
}
|
|
320
269
|
|
|
321
|
-
function test_GivenCashOutRateDneqMAX_CASH_OUT_RATE() external
|
|
270
|
+
function test_GivenCashOutRateDneqMAX_CASH_OUT_RATE() external {
|
|
322
271
|
// it will return the calculated proportion
|
|
323
272
|
|
|
324
|
-
//
|
|
325
|
-
JBAccountingContext
|
|
326
|
-
_contexts[0] = JBAccountingContext({token: address(_token), decimals: 18, currency: _currency});
|
|
273
|
+
// Register accounting context.
|
|
274
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
327
275
|
|
|
328
276
|
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
329
277
|
reservedPercent: 0,
|
|
@@ -349,43 +297,26 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
349
297
|
|
|
350
298
|
uint256 _packedMetadata = JBRulesetMetadataResolver.packRulesetMetadata(_metadata);
|
|
351
299
|
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
cycleNumber: uint48(block.timestamp),
|
|
355
|
-
id: uint48(block.timestamp),
|
|
356
|
-
basedOnId: 0,
|
|
357
|
-
start: uint48(block.timestamp),
|
|
358
|
-
duration: uint32(block.timestamp + 1000),
|
|
359
|
-
weight: 1e18,
|
|
360
|
-
weightCutPercent: 0,
|
|
361
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
362
|
-
metadata: _packedMetadata
|
|
363
|
-
});
|
|
300
|
+
// Set balance = 1e18 so surplus = 1e18 (with zero payout limits).
|
|
301
|
+
_setBalance(1e18);
|
|
364
302
|
|
|
365
|
-
|
|
366
|
-
|
|
303
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
304
|
+
_mockSurplusInfra(_packedMetadata, _emptyLimits);
|
|
367
305
|
|
|
368
|
-
// mock
|
|
369
|
-
mockExpect(address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(_controller));
|
|
370
|
-
|
|
371
|
-
// mock current surplus
|
|
306
|
+
// mock JBController totalTokenSupplyWithReservedTokensOf
|
|
372
307
|
mockExpect(
|
|
373
|
-
address(
|
|
374
|
-
abi.encodeCall(
|
|
308
|
+
address(_controller),
|
|
309
|
+
abi.encodeCall(IJBController.totalTokenSupplyWithReservedTokensOf, (_projectId)),
|
|
375
310
|
abi.encode(1e18)
|
|
376
311
|
);
|
|
377
312
|
|
|
378
|
-
// mock JBController totalTokenSupplyWithReservedTokensOf
|
|
379
|
-
bytes memory _totalTokenCall = abi.encodeCall(IJBController.totalTokenSupplyWithReservedTokensOf, (_projectId));
|
|
380
|
-
bytes memory _tokenTotal = abi.encode(1e18);
|
|
381
|
-
mockExpect(address(_controller), _totalTokenCall, _tokenTotal);
|
|
382
|
-
|
|
383
313
|
uint256 reclaimable;
|
|
384
314
|
{
|
|
385
315
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
386
316
|
_terminals[0] = _terminal;
|
|
387
|
-
reclaimable =
|
|
388
|
-
|
|
317
|
+
reclaimable = _store.currentReclaimableSurplusOf(
|
|
318
|
+
_projectId, _tokenCount, _terminals, new address[](0), 18, _currency
|
|
319
|
+
);
|
|
389
320
|
}
|
|
390
321
|
|
|
391
322
|
uint256 assumed = mulDiv(
|
|
@@ -397,10 +328,11 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
397
328
|
assertEq(assumed, reclaimable);
|
|
398
329
|
}
|
|
399
330
|
|
|
400
|
-
function test_GivenNotOverloaded() external
|
|
331
|
+
function test_GivenNotOverloaded() external {
|
|
401
332
|
// it will get the current ruleset and proceed to return reclaimable as above
|
|
402
333
|
|
|
403
|
-
//
|
|
334
|
+
// This test uses the 4-param overload (projectId, cashOutCount, totalSupply, surplus)
|
|
335
|
+
// which does not go through the store's currentSurplusOf — it takes surplus directly.
|
|
404
336
|
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
405
337
|
reservedPercent: 0,
|
|
406
338
|
cashOutTaxRate: JBConstants.MAX_CASH_OUT_TAX_RATE / 2,
|
|
@@ -425,7 +357,6 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
425
357
|
|
|
426
358
|
uint256 _packedMetadata = JBRulesetMetadataResolver.packRulesetMetadata(_metadata);
|
|
427
359
|
|
|
428
|
-
// JBRulesets return calldata
|
|
429
360
|
JBRuleset memory _returnedRuleset = JBRuleset({
|
|
430
361
|
cycleNumber: uint48(block.timestamp),
|
|
431
362
|
id: uint48(block.timestamp),
|
|
@@ -438,19 +369,17 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
438
369
|
metadata: _packedMetadata
|
|
439
370
|
});
|
|
440
371
|
|
|
441
|
-
// mock call to JBRulesets currentOf
|
|
442
372
|
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(_returnedRuleset));
|
|
443
373
|
|
|
444
374
|
uint256 reclaimable = _store.currentReclaimableSurplusOf(_projectId, _tokenCount, 1e18, 1e18);
|
|
445
375
|
assertEq(1e18, reclaimable);
|
|
446
376
|
}
|
|
447
377
|
|
|
448
|
-
function test_GivenTotalReclaimableWithSurplus() external
|
|
378
|
+
function test_GivenTotalReclaimableWithSurplus() external {
|
|
449
379
|
// it will default to all terminals and all accounting contexts and return the reclaimable surplus
|
|
450
380
|
|
|
451
|
-
//
|
|
452
|
-
JBAccountingContext
|
|
453
|
-
_contexts[0] = JBAccountingContext({token: address(_token), decimals: 18, currency: _currency});
|
|
381
|
+
// Register accounting context.
|
|
382
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
454
383
|
|
|
455
384
|
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
456
385
|
reservedPercent: 0,
|
|
@@ -476,41 +405,20 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
476
405
|
|
|
477
406
|
uint256 _packedMetadata = JBRulesetMetadataResolver.packRulesetMetadata(_metadata);
|
|
478
407
|
|
|
479
|
-
// JBRulesets return calldata
|
|
480
|
-
JBRuleset memory _returnedRuleset = JBRuleset({
|
|
481
|
-
cycleNumber: uint48(block.timestamp),
|
|
482
|
-
id: uint48(block.timestamp),
|
|
483
|
-
basedOnId: 0,
|
|
484
|
-
start: uint48(block.timestamp),
|
|
485
|
-
duration: uint32(block.timestamp + 1000),
|
|
486
|
-
weight: 1e18,
|
|
487
|
-
weightCutPercent: 0,
|
|
488
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
489
|
-
metadata: _packedMetadata
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
// mock call to JBRulesets currentOf
|
|
493
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(_returnedRuleset));
|
|
494
|
-
|
|
495
|
-
// mock call to JBDirectory controllerOf
|
|
496
|
-
mockExpect(address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(_controller));
|
|
497
|
-
|
|
498
408
|
uint256 _supply = 1e19;
|
|
499
409
|
uint256 _surplus = 1e18;
|
|
500
410
|
uint256 _cashoutAmount = 1e18;
|
|
501
411
|
|
|
502
|
-
//
|
|
412
|
+
// Set balance = surplus (with zero payout limits, surplus = balance).
|
|
413
|
+
_setBalance(_surplus);
|
|
414
|
+
|
|
415
|
+
// Mock terminalsOf to return our terminal (for currentTotalReclaimableSurplusOf which uses empty terminals).
|
|
503
416
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
504
417
|
_terminals[0] = _terminal;
|
|
505
418
|
mockExpect(address(directory), abi.encodeCall(IJBDirectory.terminalsOf, (_projectId)), abi.encode(_terminals));
|
|
506
419
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
mockExpect(
|
|
510
|
-
address(_terminal),
|
|
511
|
-
abi.encodeCall(IJBTerminal.currentSurplusOf, (_projectId, _emptyContexts, 18, _currency)),
|
|
512
|
-
abi.encode(_surplus)
|
|
513
|
-
);
|
|
420
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
421
|
+
_mockSurplusInfra(_packedMetadata, _emptyLimits);
|
|
514
422
|
|
|
515
423
|
// mock JBController totalTokenSupplyWithReservedTokensOf
|
|
516
424
|
mockExpect(
|
|
@@ -532,44 +440,28 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
532
440
|
function test_GivenTotalReclaimableWithZeroSurplus() external {
|
|
533
441
|
// it will return zero when there is no surplus
|
|
534
442
|
|
|
535
|
-
|
|
443
|
+
// Register accounting context.
|
|
444
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
536
445
|
|
|
537
|
-
//
|
|
538
|
-
JBRuleset memory _returnedRuleset = JBRuleset({
|
|
539
|
-
cycleNumber: uint48(block.timestamp),
|
|
540
|
-
id: uint48(block.timestamp),
|
|
541
|
-
basedOnId: 0,
|
|
542
|
-
start: uint48(block.timestamp),
|
|
543
|
-
duration: uint32(block.timestamp + 1000),
|
|
544
|
-
weight: 1e18,
|
|
545
|
-
weightCutPercent: 0,
|
|
546
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
547
|
-
metadata: 0
|
|
548
|
-
});
|
|
446
|
+
// No balance set — surplus is 0.
|
|
549
447
|
|
|
550
|
-
//
|
|
551
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(_returnedRuleset));
|
|
552
|
-
|
|
553
|
-
// mock JBDirectory terminalsOf to return the terminal
|
|
448
|
+
// Mock terminalsOf to return our terminal.
|
|
554
449
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
555
450
|
_terminals[0] = _terminal;
|
|
556
451
|
mockExpect(address(directory), abi.encodeCall(IJBDirectory.terminalsOf, (_projectId)), abi.encode(_terminals));
|
|
557
452
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
address(_terminal),
|
|
561
|
-
abi.encodeCall(IJBTerminal.currentSurplusOf, (_projectId, _emptyContexts, 18, _currency)),
|
|
562
|
-
abi.encode(0)
|
|
563
|
-
);
|
|
453
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
454
|
+
_mockSurplusInfra(0, _emptyLimits);
|
|
564
455
|
|
|
565
456
|
uint256 reclaimable = _store.currentTotalReclaimableSurplusOf(_projectId, _tokenCount, 18, _currency);
|
|
566
457
|
assertEq(0, reclaimable);
|
|
567
458
|
}
|
|
568
459
|
|
|
569
|
-
function test_GivenTotalReclaimableMatchesSixParamOverload() external
|
|
460
|
+
function test_GivenTotalReclaimableMatchesSixParamOverload() external {
|
|
570
461
|
// it will produce the same result as calling the 6-param overload with empty arrays
|
|
571
462
|
|
|
572
|
-
|
|
463
|
+
// Register accounting context.
|
|
464
|
+
_registerContext(JBAccountingContext({token: address(_token), decimals: 18, currency: _currency}));
|
|
573
465
|
|
|
574
466
|
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
575
467
|
reservedPercent: 0,
|
|
@@ -595,38 +487,24 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
595
487
|
|
|
596
488
|
uint256 _packedMetadata = JBRulesetMetadataResolver.packRulesetMetadata(_metadata);
|
|
597
489
|
|
|
598
|
-
JBRuleset memory _returnedRuleset = JBRuleset({
|
|
599
|
-
cycleNumber: uint48(block.timestamp),
|
|
600
|
-
id: uint48(block.timestamp),
|
|
601
|
-
basedOnId: 0,
|
|
602
|
-
start: uint48(block.timestamp),
|
|
603
|
-
duration: uint32(block.timestamp + 1000),
|
|
604
|
-
weight: 1e18,
|
|
605
|
-
weightCutPercent: 0,
|
|
606
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
607
|
-
metadata: _packedMetadata
|
|
608
|
-
});
|
|
609
|
-
|
|
610
490
|
uint256 _supply = 1e19;
|
|
611
491
|
uint256 _surplus = 5e17;
|
|
612
492
|
uint256 _cashoutAmount = 1e18;
|
|
613
493
|
|
|
494
|
+
// Set balance = surplus (with zero payout limits).
|
|
495
|
+
_setBalance(_surplus);
|
|
496
|
+
|
|
614
497
|
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
615
498
|
_terminals[0] = _terminal;
|
|
616
499
|
|
|
617
|
-
|
|
618
|
-
// Mock it to return the same ruleset both times.
|
|
619
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(_returnedRuleset));
|
|
500
|
+
JBCurrencyAmount[] memory _emptyLimits = new JBCurrencyAmount[](0);
|
|
620
501
|
|
|
621
|
-
|
|
502
|
+
// --- Call 1: currentTotalReclaimableSurplusOf (uses empty terminals -> resolves from directory) ---
|
|
622
503
|
|
|
504
|
+
// Mock terminalsOf for the total reclaimable call.
|
|
623
505
|
mockExpect(address(directory), abi.encodeCall(IJBDirectory.terminalsOf, (_projectId)), abi.encode(_terminals));
|
|
624
506
|
|
|
625
|
-
|
|
626
|
-
address(_terminal),
|
|
627
|
-
abi.encodeCall(IJBTerminal.currentSurplusOf, (_projectId, _emptyContexts, 18, _currency)),
|
|
628
|
-
abi.encode(_surplus)
|
|
629
|
-
);
|
|
507
|
+
_mockSurplusInfra(_packedMetadata, _emptyLimits);
|
|
630
508
|
|
|
631
509
|
mockExpect(
|
|
632
510
|
address(_controller),
|
|
@@ -634,27 +512,23 @@ contract TestCurrentReclaimableSurplusOf_Local is JBTerminalStoreSetup {
|
|
|
634
512
|
abi.encode(_supply)
|
|
635
513
|
);
|
|
636
514
|
|
|
637
|
-
// Call the new convenience function.
|
|
638
515
|
uint256 reclaimableDefault = _store.currentTotalReclaimableSurplusOf(_projectId, _cashoutAmount, 18, _currency);
|
|
639
516
|
|
|
640
|
-
//
|
|
641
|
-
|
|
642
|
-
|
|
517
|
+
// --- Call 2: 6-param overload with empty arrays ---
|
|
518
|
+
|
|
519
|
+
// Re-mock for the 6-param call (mocks are consumed by the first call).
|
|
643
520
|
mockExpect(address(directory), abi.encodeCall(IJBDirectory.terminalsOf, (_projectId)), abi.encode(_terminals));
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
abi.encode(_surplus)
|
|
648
|
-
);
|
|
521
|
+
|
|
522
|
+
_mockSurplusInfra(_packedMetadata, _emptyLimits);
|
|
523
|
+
|
|
649
524
|
mockExpect(
|
|
650
525
|
address(_controller),
|
|
651
526
|
abi.encodeCall(IJBController.totalTokenSupplyWithReservedTokensOf, (_projectId)),
|
|
652
527
|
abi.encode(_supply)
|
|
653
528
|
);
|
|
654
529
|
|
|
655
|
-
// Call the 6-param overload with empty arrays.
|
|
656
530
|
uint256 reclaimableExplicit = _store.currentReclaimableSurplusOf(
|
|
657
|
-
_projectId, _cashoutAmount, new IJBTerminal[](0), new
|
|
531
|
+
_projectId, _cashoutAmount, new IJBTerminal[](0), new address[](0), 18, _currency
|
|
658
532
|
);
|
|
659
533
|
|
|
660
534
|
assertEq(reclaimableDefault, reclaimableExplicit);
|