@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
|
@@ -7,7 +7,6 @@ import {IJBFeeTerminal} from "./IJBFeeTerminal.sol";
|
|
|
7
7
|
import {IJBPayoutTerminal} from "./IJBPayoutTerminal.sol";
|
|
8
8
|
import {IJBPermitTerminal} from "./IJBPermitTerminal.sol";
|
|
9
9
|
import {IJBProjects} from "./IJBProjects.sol";
|
|
10
|
-
import {IJBRulesets} from "./IJBRulesets.sol";
|
|
11
10
|
import {IJBSplits} from "./IJBSplits.sol";
|
|
12
11
|
import {IJBTerminal} from "./IJBTerminal.sol";
|
|
13
12
|
import {IJBTerminalStore} from "./IJBTerminalStore.sol";
|
|
@@ -22,9 +21,6 @@ interface IJBMultiTerminal is IJBTerminal, IJBFeeTerminal, IJBCashOutTerminal, I
|
|
|
22
21
|
/// @notice Mints ERC-721s that represent project ownership and transfers.
|
|
23
22
|
function PROJECTS() external view returns (IJBProjects);
|
|
24
23
|
|
|
25
|
-
/// @notice The contract storing and managing project rulesets.
|
|
26
|
-
function RULESETS() external view returns (IJBRulesets);
|
|
27
|
-
|
|
28
24
|
/// @notice The contract that stores splits for each project.
|
|
29
25
|
function SPLITS() external view returns (IJBSplits);
|
|
30
26
|
|
|
@@ -88,15 +88,15 @@ interface IJBTerminal is IERC165 {
|
|
|
88
88
|
/// @return The accounting contexts for the project.
|
|
89
89
|
function accountingContextsOf(uint256 projectId) external view returns (JBAccountingContext[] memory);
|
|
90
90
|
|
|
91
|
-
/// @notice Returns a project's current surplus
|
|
91
|
+
/// @notice Returns a project's current surplus in this terminal.
|
|
92
92
|
/// @param projectId The ID of the project to get the surplus of.
|
|
93
|
-
/// @param
|
|
93
|
+
/// @param tokens The tokens to include in the surplus calculation. If empty, all tokens are included.
|
|
94
94
|
/// @param decimals The number of decimals to express the surplus with.
|
|
95
95
|
/// @param currency The currency to express the surplus in.
|
|
96
|
-
/// @return The project's current surplus.
|
|
96
|
+
/// @return The project's current surplus for the given tokens.
|
|
97
97
|
function currentSurplusOf(
|
|
98
98
|
uint256 projectId,
|
|
99
|
-
|
|
99
|
+
address[] calldata tokens,
|
|
100
100
|
uint256 decimals,
|
|
101
101
|
uint256 currency
|
|
102
102
|
)
|
|
@@ -5,11 +5,11 @@ import {IJBDirectory} from "./IJBDirectory.sol";
|
|
|
5
5
|
import {IJBPrices} from "./IJBPrices.sol";
|
|
6
6
|
import {IJBRulesets} from "./IJBRulesets.sol";
|
|
7
7
|
import {IJBTerminal} from "./IJBTerminal.sol";
|
|
8
|
-
import {JBAccountingContext} from "
|
|
9
|
-
import {JBCashOutHookSpecification} from "
|
|
10
|
-
import {JBPayHookSpecification} from "
|
|
11
|
-
import {JBRuleset} from "
|
|
12
|
-
import {JBTokenAmount} from "
|
|
8
|
+
import {JBAccountingContext} from "../structs/JBAccountingContext.sol";
|
|
9
|
+
import {JBCashOutHookSpecification} from "../structs/JBCashOutHookSpecification.sol";
|
|
10
|
+
import {JBPayHookSpecification} from "../structs/JBPayHookSpecification.sol";
|
|
11
|
+
import {JBRuleset} from "../structs/JBRuleset.sol";
|
|
12
|
+
import {JBTokenAmount} from "../structs/JBTokenAmount.sol";
|
|
13
13
|
|
|
14
14
|
/// @notice Manages the bookkeeping for payments, cash outs, payouts, and surplus allowance usage for terminals.
|
|
15
15
|
interface IJBTerminalStore {
|
|
@@ -22,6 +22,32 @@ interface IJBTerminalStore {
|
|
|
22
22
|
/// @notice The contract storing and managing project rulesets.
|
|
23
23
|
function RULESETS() external view returns (IJBRulesets);
|
|
24
24
|
|
|
25
|
+
/// @notice Returns the accounting context for a terminal's project token.
|
|
26
|
+
/// @param terminal The terminal the accounting context applies to.
|
|
27
|
+
/// @param projectId The ID of the project.
|
|
28
|
+
/// @param token The token to get the accounting context for.
|
|
29
|
+
/// @return The accounting context.
|
|
30
|
+
function accountingContextOf(
|
|
31
|
+
address terminal,
|
|
32
|
+
uint256 projectId,
|
|
33
|
+
address token
|
|
34
|
+
)
|
|
35
|
+
external
|
|
36
|
+
view
|
|
37
|
+
returns (JBAccountingContext memory);
|
|
38
|
+
|
|
39
|
+
/// @notice Returns all accounting contexts for a terminal's project.
|
|
40
|
+
/// @param terminal The terminal the accounting contexts apply to.
|
|
41
|
+
/// @param projectId The ID of the project.
|
|
42
|
+
/// @return The accounting contexts.
|
|
43
|
+
function accountingContextsOf(
|
|
44
|
+
address terminal,
|
|
45
|
+
uint256 projectId
|
|
46
|
+
)
|
|
47
|
+
external
|
|
48
|
+
view
|
|
49
|
+
returns (JBAccountingContext[] memory);
|
|
50
|
+
|
|
25
51
|
/// @notice Returns the balance of a terminal for a project and token.
|
|
26
52
|
/// @param terminal The terminal to get the balance of.
|
|
27
53
|
/// @param projectId The ID of the project to get the balance for.
|
|
@@ -45,11 +71,12 @@ interface IJBTerminalStore {
|
|
|
45
71
|
view
|
|
46
72
|
returns (uint256);
|
|
47
73
|
|
|
48
|
-
/// @notice Returns the reclaimable surplus for a project across multiple terminals
|
|
74
|
+
/// @notice Returns the reclaimable surplus for a project across multiple terminals, considering only specific
|
|
75
|
+
/// tokens.
|
|
49
76
|
/// @param projectId The ID of the project.
|
|
50
77
|
/// @param cashOutCount The number of tokens being cashed out.
|
|
51
|
-
/// @param terminals The terminals to include in the surplus calculation.
|
|
52
|
-
/// @param
|
|
78
|
+
/// @param terminals The terminals to include in the surplus calculation. If empty, all project terminals are used.
|
|
79
|
+
/// @param tokens The tokens to include in the surplus calculation.
|
|
53
80
|
/// @param decimals The number of decimals to express the result with.
|
|
54
81
|
/// @param currency The currency to express the result in.
|
|
55
82
|
/// @return The reclaimable surplus amount.
|
|
@@ -57,7 +84,7 @@ interface IJBTerminalStore {
|
|
|
57
84
|
uint256 projectId,
|
|
58
85
|
uint256 cashOutCount,
|
|
59
86
|
IJBTerminal[] calldata terminals,
|
|
60
|
-
|
|
87
|
+
address[] calldata tokens,
|
|
61
88
|
uint256 decimals,
|
|
62
89
|
uint256 currency
|
|
63
90
|
)
|
|
@@ -65,15 +92,17 @@ interface IJBTerminalStore {
|
|
|
65
92
|
view
|
|
66
93
|
returns (uint256);
|
|
67
94
|
|
|
68
|
-
/// @notice Returns the
|
|
95
|
+
/// @notice Returns the current surplus for a project across specified terminals and tokens.
|
|
69
96
|
/// @param projectId The ID of the project.
|
|
70
|
-
/// @param
|
|
97
|
+
/// @param terminals The terminals to include. If empty, all project terminals are used.
|
|
98
|
+
/// @param tokens The tokens to include. If empty, all tokens per terminal are used.
|
|
71
99
|
/// @param decimals The number of decimals to express the result with.
|
|
72
100
|
/// @param currency The currency to express the result in.
|
|
73
|
-
/// @return The
|
|
74
|
-
function
|
|
101
|
+
/// @return The current surplus.
|
|
102
|
+
function currentSurplusOf(
|
|
75
103
|
uint256 projectId,
|
|
76
|
-
|
|
104
|
+
IJBTerminal[] calldata terminals,
|
|
105
|
+
address[] calldata tokens,
|
|
77
106
|
uint256 decimals,
|
|
78
107
|
uint256 currency
|
|
79
108
|
)
|
|
@@ -81,17 +110,15 @@ interface IJBTerminalStore {
|
|
|
81
110
|
view
|
|
82
111
|
returns (uint256);
|
|
83
112
|
|
|
84
|
-
/// @notice Returns the
|
|
85
|
-
/// @param terminal The terminal to get the surplus of.
|
|
113
|
+
/// @notice Returns the reclaimable surplus for a project across all terminals using all accounting contexts.
|
|
86
114
|
/// @param projectId The ID of the project.
|
|
87
|
-
/// @param
|
|
115
|
+
/// @param cashOutCount The number of tokens being cashed out.
|
|
88
116
|
/// @param decimals The number of decimals to express the result with.
|
|
89
117
|
/// @param currency The currency to express the result in.
|
|
90
|
-
/// @return The
|
|
91
|
-
function
|
|
92
|
-
address terminal,
|
|
118
|
+
/// @return The reclaimable surplus amount.
|
|
119
|
+
function currentTotalReclaimableSurplusOf(
|
|
93
120
|
uint256 projectId,
|
|
94
|
-
|
|
121
|
+
uint256 cashOutCount,
|
|
95
122
|
uint256 decimals,
|
|
96
123
|
uint256 currency
|
|
97
124
|
)
|
|
@@ -114,11 +141,11 @@ interface IJBTerminalStore {
|
|
|
114
141
|
returns (uint256);
|
|
115
142
|
|
|
116
143
|
/// @notice Simulates a cash out without modifying state.
|
|
144
|
+
/// @param terminal The terminal to simulate the cash out from.
|
|
117
145
|
/// @param holder The address cashing out.
|
|
118
146
|
/// @param projectId The ID of the project being cashed out from.
|
|
119
147
|
/// @param cashOutCount The number of project tokens being cashed out.
|
|
120
|
-
/// @param
|
|
121
|
-
/// @param balanceAccountingContexts The accounting contexts to include in the balance calculation.
|
|
148
|
+
/// @param tokenToReclaim The token being reclaimed.
|
|
122
149
|
/// @param beneficiaryIsFeeless Whether the cash out's beneficiary is a feeless address.
|
|
123
150
|
/// @param metadata Extra data to pass along to the data hook.
|
|
124
151
|
/// @return ruleset The project's current ruleset.
|
|
@@ -126,11 +153,11 @@ interface IJBTerminalStore {
|
|
|
126
153
|
/// @return cashOutTaxRate The cash out tax rate that would be applied.
|
|
127
154
|
/// @return hookSpecifications Any cash out hook specifications from the data hook.
|
|
128
155
|
function previewCashOutFrom(
|
|
156
|
+
address terminal,
|
|
129
157
|
address holder,
|
|
130
158
|
uint256 projectId,
|
|
131
159
|
uint256 cashOutCount,
|
|
132
|
-
|
|
133
|
-
JBAccountingContext[] calldata balanceAccountingContexts,
|
|
160
|
+
address tokenToReclaim,
|
|
134
161
|
bool beneficiaryIsFeeless,
|
|
135
162
|
bytes calldata metadata
|
|
136
163
|
)
|
|
@@ -144,6 +171,7 @@ interface IJBTerminalStore {
|
|
|
144
171
|
);
|
|
145
172
|
|
|
146
173
|
/// @notice Simulates a payment without modifying state.
|
|
174
|
+
/// @param terminal The terminal to simulate the payment from.
|
|
147
175
|
/// @param payer The address of the payer.
|
|
148
176
|
/// @param amount The amount being paid.
|
|
149
177
|
/// @param projectId The ID of the project being paid.
|
|
@@ -153,6 +181,7 @@ interface IJBTerminalStore {
|
|
|
153
181
|
/// @return tokenCount The number of project tokens that would be minted, including reserved tokens.
|
|
154
182
|
/// @return hookSpecifications Any pay hook specifications from the data hook.
|
|
155
183
|
function previewPayFrom(
|
|
184
|
+
address terminal,
|
|
156
185
|
address payer,
|
|
157
186
|
JBTokenAmount memory amount,
|
|
158
187
|
uint256 projectId,
|
|
@@ -199,6 +228,11 @@ interface IJBTerminalStore {
|
|
|
199
228
|
view
|
|
200
229
|
returns (uint256);
|
|
201
230
|
|
|
231
|
+
/// @notice Records accounting contexts for a terminal's project tokens.
|
|
232
|
+
/// @param projectId The ID of the project.
|
|
233
|
+
/// @param contexts The accounting contexts to record.
|
|
234
|
+
function recordAccountingContextOf(uint256 projectId, JBAccountingContext[] calldata contexts) external;
|
|
235
|
+
|
|
202
236
|
/// @notice Records a balance addition for a project.
|
|
203
237
|
/// @param projectId The ID of the project.
|
|
204
238
|
/// @param token The token being added.
|
|
@@ -209,8 +243,7 @@ interface IJBTerminalStore {
|
|
|
209
243
|
/// @param holder The address cashing out.
|
|
210
244
|
/// @param projectId The ID of the project being cashed out from.
|
|
211
245
|
/// @param cashOutCount The number of project tokens being cashed out.
|
|
212
|
-
/// @param
|
|
213
|
-
/// @param balanceAccountingContexts The accounting contexts to include in the balance calculation.
|
|
246
|
+
/// @param tokenToReclaim The token being reclaimed.
|
|
214
247
|
/// @param beneficiaryIsFeeless Whether the cash out's beneficiary is a feeless address. Passed through to data
|
|
215
248
|
/// hooks so they can skip their own fees when value stays in the protocol (e.g. project-to-project routing).
|
|
216
249
|
/// @param metadata Extra data to pass along to the data hook.
|
|
@@ -222,8 +255,7 @@ interface IJBTerminalStore {
|
|
|
222
255
|
address holder,
|
|
223
256
|
uint256 projectId,
|
|
224
257
|
uint256 cashOutCount,
|
|
225
|
-
|
|
226
|
-
JBAccountingContext[] calldata balanceAccountingContexts,
|
|
258
|
+
address tokenToReclaim,
|
|
227
259
|
bool beneficiaryIsFeeless,
|
|
228
260
|
bytes calldata metadata
|
|
229
261
|
)
|
|
@@ -256,14 +288,14 @@ interface IJBTerminalStore {
|
|
|
256
288
|
|
|
257
289
|
/// @notice Records a payout from a project.
|
|
258
290
|
/// @param projectId The ID of the project paying out.
|
|
259
|
-
/// @param
|
|
291
|
+
/// @param token The token being paid out.
|
|
260
292
|
/// @param amount The amount being paid out.
|
|
261
293
|
/// @param currency The currency the amount is denominated in.
|
|
262
294
|
/// @return ruleset The project's current ruleset.
|
|
263
295
|
/// @return amountPaidOut The amount paid out in the token's native decimals.
|
|
264
296
|
function recordPayoutFor(
|
|
265
297
|
uint256 projectId,
|
|
266
|
-
|
|
298
|
+
address token,
|
|
267
299
|
uint256 amount,
|
|
268
300
|
uint256 currency
|
|
269
301
|
)
|
|
@@ -278,14 +310,14 @@ interface IJBTerminalStore {
|
|
|
278
310
|
|
|
279
311
|
/// @notice Records surplus allowance usage for a project.
|
|
280
312
|
/// @param projectId The ID of the project using surplus allowance.
|
|
281
|
-
/// @param
|
|
313
|
+
/// @param token The token being used.
|
|
282
314
|
/// @param amount The amount of surplus allowance to use.
|
|
283
315
|
/// @param currency The currency the amount is denominated in.
|
|
284
316
|
/// @return ruleset The project's current ruleset.
|
|
285
317
|
/// @return usedAmount The amount used in the token's native decimals.
|
|
286
318
|
function recordUsedAllowanceOf(
|
|
287
319
|
uint256 projectId,
|
|
288
|
-
|
|
320
|
+
address token,
|
|
289
321
|
uint256 amount,
|
|
290
322
|
uint256 currency
|
|
291
323
|
)
|
|
@@ -3,7 +3,6 @@ pragma solidity 0.8.26;
|
|
|
3
3
|
|
|
4
4
|
import {mulDiv} from "@prb/math/src/Common.sol";
|
|
5
5
|
|
|
6
|
-
import {IJBPayoutTerminal} from "../interfaces/IJBPayoutTerminal.sol";
|
|
7
6
|
import {IJBSplits} from "../interfaces/IJBSplits.sol";
|
|
8
7
|
import {IJBTerminalStore} from "../interfaces/IJBTerminalStore.sol";
|
|
9
8
|
import {JBSplit} from "../structs/JBSplit.sol";
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
pragma solidity ^0.8.17;
|
|
3
3
|
|
|
4
4
|
import {IJBTerminal} from "../interfaces/IJBTerminal.sol";
|
|
5
|
-
import {JBAccountingContext} from "../structs/JBAccountingContext.sol";
|
|
6
5
|
|
|
7
6
|
/// @notice Surplus calculations.
|
|
8
7
|
library JBSurplus {
|
|
@@ -11,7 +10,7 @@ library JBSurplus {
|
|
|
11
10
|
/// the project's payout limits.
|
|
12
11
|
/// @param projectId The ID of the project to get the total surplus for.
|
|
13
12
|
/// @param terminals The terminals to look for surplus within.
|
|
14
|
-
/// @param
|
|
13
|
+
/// @param tokens The tokens to include in the surplus calculation. If empty, all tokens are included.
|
|
15
14
|
/// @param decimals The number of decimals that the fixed point surplus result should include.
|
|
16
15
|
/// @param currency The currency that the surplus result should be in terms of.
|
|
17
16
|
/// @return surplus The total surplus of a project's funds in terms of `currency`, as a fixed point number with the
|
|
@@ -19,7 +18,7 @@ library JBSurplus {
|
|
|
19
18
|
function currentSurplusOf(
|
|
20
19
|
uint256 projectId,
|
|
21
20
|
IJBTerminal[] memory terminals,
|
|
22
|
-
|
|
21
|
+
address[] memory tokens,
|
|
23
22
|
uint256 decimals,
|
|
24
23
|
uint256 currency
|
|
25
24
|
)
|
|
@@ -33,7 +32,7 @@ library JBSurplus {
|
|
|
33
32
|
// Add the current surplus for each terminal.
|
|
34
33
|
for (uint256 i; i < numberOfTerminals; i++) {
|
|
35
34
|
surplus += terminals[i].currentSurplusOf({
|
|
36
|
-
projectId: projectId,
|
|
35
|
+
projectId: projectId, tokens: tokens, decimals: decimals, currency: currency
|
|
37
36
|
});
|
|
38
37
|
}
|
|
39
38
|
}
|
|
@@ -4,6 +4,7 @@ pragma solidity ^0.8.6;
|
|
|
4
4
|
import {StdInvariant} from "forge-std/StdInvariant.sol";
|
|
5
5
|
import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
|
|
6
6
|
import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
7
|
+
import {IJBTerminal} from "../src/interfaces/IJBTerminal.sol";
|
|
7
8
|
import {IJBSplitHook} from "../src/interfaces/IJBSplitHook.sol";
|
|
8
9
|
import {IJBToken} from "../src/interfaces/IJBToken.sol";
|
|
9
10
|
import {JBConstants} from "../src/libraries/JBConstants.sol";
|
|
@@ -236,16 +237,13 @@ contract ComprehensiveInvariant_Local is StdInvariant, TestBaseWorkflow {
|
|
|
236
237
|
uint256 totalSupply = jbTokens().totalSupplyOf(projectId);
|
|
237
238
|
if (totalSupply == 0) return;
|
|
238
239
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
242
|
-
});
|
|
243
|
-
|
|
240
|
+
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
241
|
+
_terminals[0] = IJBTerminal(jbMultiTerminal());
|
|
244
242
|
uint256 surplus = jbTerminalStore()
|
|
245
243
|
.currentSurplusOf({
|
|
246
|
-
terminal: address(jbMultiTerminal()),
|
|
247
244
|
projectId: projectId,
|
|
248
|
-
|
|
245
|
+
terminals: _terminals,
|
|
246
|
+
tokens: new address[](0),
|
|
249
247
|
decimals: 18,
|
|
250
248
|
currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
251
249
|
});
|
|
@@ -5,6 +5,7 @@ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
|
|
|
5
5
|
import {MetadataResolverHelper} from "./helpers/MetadataResolverHelper.sol";
|
|
6
6
|
import {MockERC20} from "./mock/MockERC20.sol";
|
|
7
7
|
import {JBMultiTerminal} from "../src/JBMultiTerminal.sol";
|
|
8
|
+
import {JBTerminalStore} from "../src/JBTerminalStore.sol";
|
|
8
9
|
import {JBTokens} from "../src/JBTokens.sol";
|
|
9
10
|
import {JBApprovalStatus} from "../src/enums/JBApprovalStatus.sol";
|
|
10
11
|
import {IJBController} from "../src/interfaces/IJBController.sol";
|
|
@@ -624,16 +625,13 @@ contract EdgeCases_Local is TestBaseWorkflow {
|
|
|
624
625
|
});
|
|
625
626
|
|
|
626
627
|
// The surplus should be payAmount - payoutLimit = 15 ether.
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
630
|
-
});
|
|
631
|
-
|
|
628
|
+
IJBTerminal[] memory _surplusTerminals = new IJBTerminal[](1);
|
|
629
|
+
_surplusTerminals[0] = IJBTerminal(_terminal);
|
|
632
630
|
uint256 surplus = jbTerminalStore()
|
|
633
631
|
.currentSurplusOf({
|
|
634
|
-
terminal: address(_terminal),
|
|
635
632
|
projectId: projectId,
|
|
636
|
-
|
|
633
|
+
terminals: _surplusTerminals,
|
|
634
|
+
tokens: new address[](0),
|
|
637
635
|
decimals: 18,
|
|
638
636
|
currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
639
637
|
});
|
|
@@ -2461,7 +2459,7 @@ contract EdgeCases_Local is TestBaseWorkflow {
|
|
|
2461
2459
|
});
|
|
2462
2460
|
|
|
2463
2461
|
vm.prank(_projectOwner);
|
|
2464
|
-
vm.expectRevert(
|
|
2462
|
+
vm.expectRevert(JBTerminalStore.JBTerminalStore_AccountingContextDecimalsMismatch.selector);
|
|
2465
2463
|
_terminal.addAccountingContextsFor(projectId, wrongContexts);
|
|
2466
2464
|
}
|
|
2467
2465
|
|
|
@@ -2492,15 +2490,13 @@ contract EdgeCases_Local is TestBaseWorkflow {
|
|
|
2492
2490
|
});
|
|
2493
2491
|
|
|
2494
2492
|
// Check surplus — should equal the full balance since no payout limits.
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
JBAccountingContext({token: address(token), decimals: 6, currency: uint32(uint160(address(token)))});
|
|
2498
|
-
|
|
2493
|
+
IJBTerminal[] memory _surplusTerminals2 = new IJBTerminal[](1);
|
|
2494
|
+
_surplusTerminals2[0] = IJBTerminal(_terminal);
|
|
2499
2495
|
uint256 surplus = jbTerminalStore()
|
|
2500
2496
|
.currentSurplusOf({
|
|
2501
|
-
terminal: address(_terminal),
|
|
2502
2497
|
projectId: projectId,
|
|
2503
|
-
|
|
2498
|
+
terminals: _surplusTerminals2,
|
|
2499
|
+
tokens: new address[](0),
|
|
2504
2500
|
decimals: 6,
|
|
2505
2501
|
currency: uint32(uint160(address(token)))
|
|
2506
2502
|
});
|
|
@@ -2572,17 +2568,14 @@ contract EdgeCases_Local is TestBaseWorkflow {
|
|
|
2572
2568
|
uint256 pendingReserved = _controller.pendingReservedTokenBalanceOf(projectId);
|
|
2573
2569
|
|
|
2574
2570
|
// Record surplus before distributing reserves
|
|
2575
|
-
JBAccountingContext[] memory contexts = new JBAccountingContext[](1);
|
|
2576
|
-
contexts[0] = JBAccountingContext({
|
|
2577
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
2578
|
-
});
|
|
2579
|
-
|
|
2580
2571
|
uint256 supplyBefore = _tokens.totalSupplyOf(projectId);
|
|
2572
|
+
IJBTerminal[] memory _surplusTerminals3 = new IJBTerminal[](1);
|
|
2573
|
+
_surplusTerminals3[0] = IJBTerminal(_terminal);
|
|
2581
2574
|
uint256 surplusBefore = jbTerminalStore()
|
|
2582
2575
|
.currentSurplusOf({
|
|
2583
|
-
terminal: address(_terminal),
|
|
2584
2576
|
projectId: projectId,
|
|
2585
|
-
|
|
2577
|
+
terminals: _surplusTerminals3,
|
|
2578
|
+
tokens: new address[](0),
|
|
2586
2579
|
decimals: 18,
|
|
2587
2580
|
currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
2588
2581
|
});
|
|
@@ -2599,11 +2592,13 @@ contract EdgeCases_Local is TestBaseWorkflow {
|
|
|
2599
2592
|
}
|
|
2600
2593
|
|
|
2601
2594
|
uint256 supplyAfter = _tokens.totalSupplyOf(projectId);
|
|
2595
|
+
IJBTerminal[] memory _surplusTerminals4 = new IJBTerminal[](1);
|
|
2596
|
+
_surplusTerminals4[0] = IJBTerminal(_terminal);
|
|
2602
2597
|
uint256 surplusAfter = jbTerminalStore()
|
|
2603
2598
|
.currentSurplusOf({
|
|
2604
|
-
terminal: address(_terminal),
|
|
2605
2599
|
projectId: projectId,
|
|
2606
|
-
|
|
2600
|
+
terminals: _surplusTerminals4,
|
|
2601
|
+
tokens: new address[](0),
|
|
2607
2602
|
decimals: 18,
|
|
2608
2603
|
currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
2609
2604
|
});
|
package/test/TestCashOut.sol
CHANGED
|
@@ -131,15 +131,15 @@ contract TestCashOut_Local is TestBaseWorkflow {
|
|
|
131
131
|
// Fuzz 1 to full balance cash out.
|
|
132
132
|
_tokenAmountToCashOut = bound(_tokenAmountToCashOut, 1, _beneficiaryTokenBalance);
|
|
133
133
|
|
|
134
|
-
JBAccountingContext[] memory _tokensContext = new JBAccountingContext[](1);
|
|
135
|
-
_tokensContext[0] = JBAccountingContext({
|
|
136
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
137
|
-
});
|
|
138
|
-
|
|
139
134
|
// Get the expected gross per a different view.
|
|
140
135
|
uint256 _grossPerReclaimable = jbTerminalStore()
|
|
141
136
|
.currentReclaimableSurplusOf(
|
|
142
|
-
_projectId,
|
|
137
|
+
_projectId,
|
|
138
|
+
_tokenAmountToCashOut,
|
|
139
|
+
new IJBTerminal[](0),
|
|
140
|
+
new address[](0),
|
|
141
|
+
18,
|
|
142
|
+
uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
143
143
|
);
|
|
144
144
|
|
|
145
145
|
// Test: cash out.
|
|
@@ -162,13 +162,13 @@ contract TestMultiTerminalSurplus_Local is TestBaseWorkflow {
|
|
|
162
162
|
// Check ETH-only surplus from terminal 1.
|
|
163
163
|
JBAccountingContext[] memory ethCtx = new JBAccountingContext[](1);
|
|
164
164
|
ethCtx[0] = JBAccountingContext({token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: _nativeCurrency});
|
|
165
|
-
uint256 ethSurplus = _terminal1.currentSurplusOf(_projectId,
|
|
165
|
+
uint256 ethSurplus = _terminal1.currentSurplusOf(_projectId, new address[](0), 18, _nativeCurrency);
|
|
166
166
|
assertEq(ethSurplus, ethAmount, "terminal1 ETH surplus should match payment");
|
|
167
167
|
|
|
168
168
|
// Check USDC-only surplus from terminal 2.
|
|
169
169
|
JBAccountingContext[] memory usdcCtx = new JBAccountingContext[](1);
|
|
170
170
|
usdcCtx[0] = JBAccountingContext({token: address(_usdc), decimals: 6, currency: _usdcCurrency});
|
|
171
|
-
uint256 usdcSurplus = _terminal2.currentSurplusOf(_projectId,
|
|
171
|
+
uint256 usdcSurplus = _terminal2.currentSurplusOf(_projectId, new address[](0), 6, _usdcCurrency);
|
|
172
172
|
assertEq(usdcSurplus, usdcAmount, "terminal2 USDC surplus should match payment");
|
|
173
173
|
|
|
174
174
|
// Check total surplus in ETH terms from the store.
|
|
@@ -330,12 +330,12 @@ contract TestMultiTerminalSurplus_Local is TestBaseWorkflow {
|
|
|
330
330
|
// Get individual surpluses in ETH terms.
|
|
331
331
|
JBAccountingContext[] memory ethCtx = new JBAccountingContext[](1);
|
|
332
332
|
ethCtx[0] = JBAccountingContext({token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: _nativeCurrency});
|
|
333
|
-
uint256 t1Surplus = _terminal1.currentSurplusOf(_projectId,
|
|
333
|
+
uint256 t1Surplus = _terminal1.currentSurplusOf(_projectId, new address[](0), 18, _nativeCurrency);
|
|
334
334
|
|
|
335
335
|
JBAccountingContext[] memory usdcCtx = new JBAccountingContext[](1);
|
|
336
336
|
usdcCtx[0] = JBAccountingContext({token: address(_usdc), decimals: 6, currency: _usdcCurrency});
|
|
337
337
|
// Get terminal 2 surplus in ETH terms.
|
|
338
|
-
uint256 t2SurplusInEth = _terminal2.currentSurplusOf(_projectId,
|
|
338
|
+
uint256 t2SurplusInEth = _terminal2.currentSurplusOf(_projectId, new address[](0), 18, _nativeCurrency);
|
|
339
339
|
|
|
340
340
|
// Get total surplus from the store.
|
|
341
341
|
uint256 totalSurplus = jbTerminalStore().currentTotalSurplusOf(_projectId, 18, _nativeCurrency);
|
|
@@ -114,7 +114,7 @@ contract TestMultiTokenSurplus_Local is TestBaseWorkflow {
|
|
|
114
114
|
JBAccountingContext[] memory contexts = new JBAccountingContext[](1);
|
|
115
115
|
contexts[0] = JBAccountingContext({token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: _nativeCurrency});
|
|
116
116
|
|
|
117
|
-
uint256 surplus = _terminal.currentSurplusOf(_projectId,
|
|
117
|
+
uint256 surplus = _terminal.currentSurplusOf(_projectId, new address[](0), 18, _nativeCurrency);
|
|
118
118
|
assertEq(surplus, payAmount, "ETH surplus should match payment");
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -137,7 +137,7 @@ contract TestMultiTokenSurplus_Local is TestBaseWorkflow {
|
|
|
137
137
|
JBAccountingContext[] memory contexts = new JBAccountingContext[](1);
|
|
138
138
|
contexts[0] = JBAccountingContext({token: address(_usdc), decimals: 6, currency: _usdcCurrency});
|
|
139
139
|
|
|
140
|
-
uint256 surplus = _terminal.currentSurplusOf(_projectId,
|
|
140
|
+
uint256 surplus = _terminal.currentSurplusOf(_projectId, new address[](0), 6, _usdcCurrency);
|
|
141
141
|
assertEq(surplus, usdcAmount, "USDC surplus should match payment");
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -162,30 +162,13 @@ contract TestMultiTokenSurplus_Local is TestBaseWorkflow {
|
|
|
162
162
|
vm.prank(_beneficiary);
|
|
163
163
|
_terminal.pay(_projectId, address(_usdc), usdcAmount, _beneficiary, 0, "", "");
|
|
164
164
|
|
|
165
|
-
// Check surplus
|
|
166
|
-
|
|
167
|
-
ethContext[0] = JBAccountingContext({token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: _nativeCurrency});
|
|
165
|
+
// Check surplus (now includes all registered contexts automatically)
|
|
166
|
+
uint256 ethSurplus = _terminal.currentSurplusOf(_projectId, new address[](0), 18, _nativeCurrency);
|
|
168
167
|
|
|
169
|
-
|
|
170
|
-
usdcContext[0] = JBAccountingContext({token: address(_usdc), decimals: 6, currency: _usdcCurrency});
|
|
171
|
-
|
|
172
|
-
uint256 ethSurplus = _terminal.currentSurplusOf(_projectId, ethContext, 18, _nativeCurrency);
|
|
173
|
-
assertEq(ethSurplus, ethAmount, "ETH surplus should match");
|
|
174
|
-
|
|
175
|
-
uint256 usdcSurplus = _terminal.currentSurplusOf(_projectId, usdcContext, 6, _usdcCurrency);
|
|
176
|
-
assertEq(usdcSurplus, usdcAmount, "USDC surplus should match");
|
|
177
|
-
|
|
178
|
-
// Check aggregated surplus in ETH terms (both contexts)
|
|
179
|
-
JBAccountingContext[] memory bothContexts = new JBAccountingContext[](2);
|
|
180
|
-
bothContexts[0] = ethContext[0];
|
|
181
|
-
bothContexts[1] = usdcContext[0];
|
|
182
|
-
|
|
183
|
-
uint256 totalSurplus = _terminal.currentSurplusOf(_projectId, bothContexts, 18, _nativeCurrency);
|
|
184
|
-
|
|
185
|
-
// Total should be ETH amount + USDC converted to ETH
|
|
168
|
+
// Total should include ETH amount + USDC converted to ETH
|
|
186
169
|
// 1 ETH + (2000 USDC / 2000 per ETH) = 2 ETH
|
|
187
170
|
// But the conversion depends on the feed direction
|
|
188
|
-
assertGt(
|
|
171
|
+
assertGt(ethSurplus, ethAmount, "total surplus should include both tokens");
|
|
189
172
|
}
|
|
190
173
|
|
|
191
174
|
/// @notice Balance tracking is per-token.
|
|
@@ -144,13 +144,8 @@ contract TestTerminalMigration_Local is TestBaseWorkflow {
|
|
|
144
144
|
_terminalA.pay{value: payAmount}(_projectId, JBConstants.NATIVE_TOKEN, payAmount, _beneficiary, 0, "", "");
|
|
145
145
|
|
|
146
146
|
// Record surplus before migration
|
|
147
|
-
JBAccountingContext[] memory contexts = new JBAccountingContext[](1);
|
|
148
|
-
contexts[0] = JBAccountingContext({
|
|
149
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
150
|
-
});
|
|
151
|
-
|
|
152
147
|
uint256 surplusBefore =
|
|
153
|
-
_terminalA.currentSurplusOf(_projectId,
|
|
148
|
+
_terminalA.currentSurplusOf(_projectId, new address[](0), 18, uint32(uint160(JBConstants.NATIVE_TOKEN)));
|
|
154
149
|
assertGt(surplusBefore, 0, "should have surplus before migration");
|
|
155
150
|
|
|
156
151
|
// Migrate
|
|
@@ -159,7 +154,7 @@ contract TestTerminalMigration_Local is TestBaseWorkflow {
|
|
|
159
154
|
|
|
160
155
|
// Check surplus from terminal B
|
|
161
156
|
uint256 surplusAfter =
|
|
162
|
-
_terminalB.currentSurplusOf(_projectId,
|
|
157
|
+
_terminalB.currentSurplusOf(_projectId, new address[](0), 18, uint32(uint160(JBConstants.NATIVE_TOKEN)));
|
|
163
158
|
assertEq(surplusAfter, surplusBefore, "surplus should be preserved after migration");
|
|
164
159
|
}
|
|
165
160
|
|
|
@@ -59,7 +59,7 @@ contract TestSequencerPriceFeedFork is Test {
|
|
|
59
59
|
// ------------------------------------------------------------------
|
|
60
60
|
|
|
61
61
|
/// @notice Under normal conditions (sequencer up, grace period elapsed), currentUnitPrice returns a sane price.
|
|
62
|
-
function test_normalOperation_returnsValidPrice() public skipIfNoRpc {
|
|
62
|
+
function test_normalOperation_returnsValidPrice() public view skipIfNoRpc {
|
|
63
63
|
uint256 price18 = feed.currentUnitPrice(18);
|
|
64
64
|
|
|
65
65
|
// ETH price should be between $500 and $50,000.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
pragma solidity ^0.8.26;
|
|
3
3
|
|
|
4
4
|
import {TestTerminalPreviewParity_Local} from "../TestTerminalPreviewParity.sol";
|
|
5
|
-
import {IJBController} from "../../src/interfaces/IJBController.sol";
|
|
6
5
|
import {IJBTerminal} from "../../src/interfaces/IJBTerminal.sol";
|
|
7
6
|
import {IJBCashOutTerminal} from "../../src/interfaces/IJBCashOutTerminal.sol";
|
|
8
7
|
import {JBConstants} from "../../src/libraries/JBConstants.sol";
|
|
@@ -4,6 +4,7 @@ pragma solidity ^0.8.6;
|
|
|
4
4
|
import {StdInvariant} from "forge-std/StdInvariant.sol";
|
|
5
5
|
import {TestBaseWorkflow} from "../helpers/TestBaseWorkflow.sol";
|
|
6
6
|
import {IJBRulesetApprovalHook} from "../../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
7
|
+
import {IJBTerminal} from "../../src/interfaces/IJBTerminal.sol";
|
|
7
8
|
import {JBConstants} from "../../src/libraries/JBConstants.sol";
|
|
8
9
|
import {JBRulesetMetadataResolver} from "../../src/libraries/JBRulesetMetadataResolver.sol";
|
|
9
10
|
import {JBFundAccessLimitGroup} from "../../src/structs/JBFundAccessLimitGroup.sol";
|
|
@@ -153,16 +154,13 @@ contract TerminalStoreInvariant_Local is StdInvariant, TestBaseWorkflow {
|
|
|
153
154
|
uint256 totalSupply = jbTokens().totalSupplyOf(projectId);
|
|
154
155
|
if (totalSupply == 0) return; // Skip when no tokens exist
|
|
155
156
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
159
|
-
});
|
|
160
|
-
|
|
157
|
+
IJBTerminal[] memory _terminals = new IJBTerminal[](1);
|
|
158
|
+
_terminals[0] = IJBTerminal(jbMultiTerminal());
|
|
161
159
|
uint256 surplus = jbTerminalStore()
|
|
162
160
|
.currentSurplusOf({
|
|
163
|
-
terminal: address(jbMultiTerminal()),
|
|
164
161
|
projectId: projectId,
|
|
165
|
-
|
|
162
|
+
terminals: _terminals,
|
|
163
|
+
tokens: new address[](0),
|
|
166
164
|
decimals: 18,
|
|
167
165
|
currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
168
166
|
});
|
|
@@ -37,9 +37,8 @@ contract JBMultiTerminalSetup is JBTest {
|
|
|
37
37
|
address trustedForwarder = makeAddr("forwarder");
|
|
38
38
|
|
|
39
39
|
function multiTerminalSetup() public virtual {
|
|
40
|
-
// Constructor will call to find directory
|
|
40
|
+
// Constructor will call to find directory from the terminal store
|
|
41
41
|
mockExpect(address(store), abi.encodeCall(IJBTerminalStore.DIRECTORY, ()), abi.encode(address(directory)));
|
|
42
|
-
mockExpect(address(store), abi.encodeCall(IJBTerminalStore.RULESETS, ()), abi.encode(address(rulesets)));
|
|
43
42
|
|
|
44
43
|
// Instantiate the contract being tested
|
|
45
44
|
_terminal = new JBMultiTerminal(
|