@bananapus/core-v6 0.0.20 → 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 +3 -4
- 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
|
@@ -10,7 +10,6 @@ import {IJBController} from "../../../../src/interfaces/IJBController.sol";
|
|
|
10
10
|
import {IJBDirectory} from "../../../../src/interfaces/IJBDirectory.sol";
|
|
11
11
|
import {IJBFeelessAddresses} from "../../../../src/interfaces/IJBFeelessAddresses.sol";
|
|
12
12
|
import {IJBPermissions} from "../../../../src/interfaces/IJBPermissions.sol";
|
|
13
|
-
import {IJBRulesets} from "../../../../src/interfaces/IJBRulesets.sol";
|
|
14
13
|
import {IJBRulesetApprovalHook} from "../../../../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
15
14
|
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
16
15
|
import {JBConstants} from "../../../../src/libraries/JBConstants.sol";
|
|
@@ -22,7 +21,6 @@ import {JBRuleset} from "../../../../src/structs/JBRuleset.sol";
|
|
|
22
21
|
import {JBTokenAmount} from "../../../../src/structs/JBTokenAmount.sol";
|
|
23
22
|
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
24
23
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
25
|
-
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
26
24
|
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
27
25
|
import {JBMultiTerminalSetup} from "./JBMultiTerminalSetup.sol";
|
|
28
26
|
|
|
@@ -54,29 +52,28 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
54
52
|
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
55
53
|
);
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
// Mock ERC20 transfer for non-contract token addresses (needed for SafeERC20 calls later).
|
|
56
|
+
if (token != JBConstants.NATIVE_TOKEN && token.code.length == 0) {
|
|
57
|
+
vm.mockCall(token, abi.encodeWithSelector(IERC20.transfer.selector), abi.encode(true));
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
JBAccountingContext[] memory _tokens = new JBAccountingContext[](1);
|
|
62
61
|
_tokens[0] = JBAccountingContext({token: token, decimals: decimals, currency: currency});
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
start: 0,
|
|
69
|
-
duration: 0,
|
|
70
|
-
weight: 0,
|
|
71
|
-
weightCutPercent: 0,
|
|
72
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
73
|
-
metadata: 0
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(returnedRuleset));
|
|
63
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
64
|
+
mockExpect(
|
|
65
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
66
|
+
);
|
|
77
67
|
|
|
78
68
|
vm.prank(address(this));
|
|
79
69
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
70
|
+
|
|
71
|
+
// Mock accountingContextOf for subsequent reads (not all code paths call it, so use mockCall only)
|
|
72
|
+
vm.mockCall(
|
|
73
|
+
address(store),
|
|
74
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, token)),
|
|
75
|
+
abi.encode(_tokens[0])
|
|
76
|
+
);
|
|
80
77
|
}
|
|
81
78
|
|
|
82
79
|
function test_WhenCallerDNHavePermission() external {
|
|
@@ -125,7 +122,8 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
125
122
|
uint256 reclaimAmount = 1e9;
|
|
126
123
|
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](0);
|
|
127
124
|
JBAccountingContext memory mockTokenContext =
|
|
128
|
-
|
|
125
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
126
|
+
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
129
127
|
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
130
128
|
mockBalanceContext[0] = mockTokenContext;
|
|
131
129
|
JBRuleset memory returnedRuleset = JBRuleset({
|
|
@@ -148,7 +146,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
148
146
|
address(store),
|
|
149
147
|
abi.encodeCall(
|
|
150
148
|
IJBTerminalStore.recordCashOutFor,
|
|
151
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext,
|
|
149
|
+
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
152
150
|
),
|
|
153
151
|
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
154
152
|
);
|
|
@@ -165,6 +163,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
165
163
|
|
|
166
164
|
// put code at mockToken address to pass OZ Address check
|
|
167
165
|
vm.etch(_mockToken, abi.encode(1));
|
|
166
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
168
167
|
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
169
168
|
|
|
170
169
|
vm.prank(_bene);
|
|
@@ -177,7 +176,8 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
177
176
|
uint256 reclaimAmount = 1e9;
|
|
178
177
|
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](0);
|
|
179
178
|
JBAccountingContext memory mockTokenContext =
|
|
180
|
-
|
|
179
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
180
|
+
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
181
181
|
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
182
182
|
mockBalanceContext[0] = mockTokenContext;
|
|
183
183
|
JBRuleset memory returnedRuleset = JBRuleset({
|
|
@@ -200,7 +200,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
200
200
|
address(store),
|
|
201
201
|
abi.encodeCall(
|
|
202
202
|
IJBTerminalStore.recordCashOutFor,
|
|
203
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext,
|
|
203
|
+
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
204
204
|
),
|
|
205
205
|
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
206
206
|
);
|
|
@@ -217,6 +217,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
217
217
|
|
|
218
218
|
// put code at mockToken address to pass OZ Address check
|
|
219
219
|
vm.etch(_mockToken, abi.encode(1));
|
|
220
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
220
221
|
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
221
222
|
|
|
222
223
|
vm.expectRevert(
|
|
@@ -238,7 +239,8 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
238
239
|
uint256 reclaimAmount = 1e9;
|
|
239
240
|
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](0);
|
|
240
241
|
JBAccountingContext memory mockTokenContext =
|
|
241
|
-
|
|
242
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
243
|
+
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
242
244
|
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
243
245
|
mockBalanceContext[0] = mockTokenContext;
|
|
244
246
|
JBRuleset memory returnedRuleset = JBRuleset({
|
|
@@ -261,7 +263,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
261
263
|
address(store),
|
|
262
264
|
abi.encodeCall(
|
|
263
265
|
IJBTerminalStore.recordCashOutFor,
|
|
264
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext,
|
|
266
|
+
(_holder, _projectId, _defaultAmount, mockTokenContext.token, false, "")
|
|
265
267
|
),
|
|
266
268
|
abi.encode(returnedRuleset, reclaimAmount, _halfCashOutTaxRate, hookSpecifications)
|
|
267
269
|
);
|
|
@@ -278,6 +280,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
278
280
|
|
|
279
281
|
// put code at mockToken address to pass OZ Address check
|
|
280
282
|
vm.etch(_mockToken, abi.encode(1));
|
|
283
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
281
284
|
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
282
285
|
|
|
283
286
|
// get fee amount
|
|
@@ -378,7 +381,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
378
381
|
address(store),
|
|
379
382
|
abi.encodeCall(
|
|
380
383
|
IJBTerminalStore.recordCashOutFor,
|
|
381
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext,
|
|
384
|
+
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
382
385
|
),
|
|
383
386
|
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
384
387
|
);
|
|
@@ -495,7 +498,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
495
498
|
address(store),
|
|
496
499
|
abi.encodeCall(
|
|
497
500
|
IJBTerminalStore.recordCashOutFor,
|
|
498
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext,
|
|
501
|
+
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
499
502
|
),
|
|
500
503
|
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
501
504
|
);
|
|
@@ -583,7 +586,8 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
583
586
|
hookSpecifications[0] =
|
|
584
587
|
JBCashOutHookSpecification({hook: IJBCashOutHook(address(this)), noop: true, amount: 0, metadata: "info"});
|
|
585
588
|
JBAccountingContext memory mockTokenContext =
|
|
586
|
-
|
|
589
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
590
|
+
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
587
591
|
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
588
592
|
mockBalanceContext[0] = mockTokenContext;
|
|
589
593
|
JBRuleset memory returnedRuleset = JBRuleset({
|
|
@@ -603,7 +607,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
603
607
|
address(store),
|
|
604
608
|
abi.encodeCall(
|
|
605
609
|
IJBTerminalStore.recordCashOutFor,
|
|
606
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext,
|
|
610
|
+
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
607
611
|
),
|
|
608
612
|
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
609
613
|
);
|
|
@@ -614,6 +618,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
|
614
618
|
address(this), abi.encodeCall(IJBController.burnTokensOf, (_holder, _projectId, _defaultAmount, "")), ""
|
|
615
619
|
);
|
|
616
620
|
|
|
621
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
617
622
|
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
618
623
|
|
|
619
624
|
vm.prank(_bene);
|
|
@@ -10,6 +10,7 @@ import {IJBTerminal} from "../../../../src/interfaces/IJBTerminal.sol";
|
|
|
10
10
|
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
11
11
|
import {JBConstants} from "../../../../src/libraries/JBConstants.sol";
|
|
12
12
|
import {JBFees} from "../../../../src/libraries/JBFees.sol";
|
|
13
|
+
import {JBAccountingContext} from "../../../../src/structs/JBAccountingContext.sol";
|
|
13
14
|
import {JBPayHookSpecification} from "../../../../src/structs/JBPayHookSpecification.sol";
|
|
14
15
|
import {JBRuleset} from "../../../../src/structs/JBRuleset.sol";
|
|
15
16
|
import {JBSplit} from "../../../../src/structs/JBSplit.sol";
|
|
@@ -32,6 +33,7 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup {
|
|
|
32
33
|
|
|
33
34
|
address _native = JBConstants.NATIVE_TOKEN;
|
|
34
35
|
address _usdc = makeAddr("USDC");
|
|
36
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
35
37
|
uint32 _usdcCurrency = uint32(uint160(_usdc));
|
|
36
38
|
|
|
37
39
|
JBSplit private _split;
|
|
@@ -42,10 +44,12 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup {
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
function _setAccountingContext(uint256 projectId, address token, uint8 decimals, uint32 currency) internal {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// Mock the store to return this accounting context
|
|
48
|
+
mockExpect(
|
|
49
|
+
address(store),
|
|
50
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), projectId, token)),
|
|
51
|
+
abi.encode(JBAccountingContext({token: token, decimals: decimals, currency: currency}))
|
|
52
|
+
);
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
modifier whenASplitHookIsConfigured() {
|
|
@@ -66,6 +70,13 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup {
|
|
|
66
70
|
function test_GivenTheSplitHookEQFeeless() external whenASplitHookIsConfigured {
|
|
67
71
|
// it will not process a fee
|
|
68
72
|
|
|
73
|
+
// Mock accountingContextOf for the decimals lookup in executePayout
|
|
74
|
+
mockExpect(
|
|
75
|
+
address(store),
|
|
76
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _noProject, _native)),
|
|
77
|
+
abi.encode(JBAccountingContext({token: _native, decimals: 0, currency: 0}))
|
|
78
|
+
);
|
|
79
|
+
|
|
69
80
|
// mock call to split hook supportsInterface
|
|
70
81
|
mockExpect(
|
|
71
82
|
address(_hook),
|
|
@@ -111,6 +122,13 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup {
|
|
|
111
122
|
function test_GivenTheSplitHookDNEQFeeless() external whenASplitHookIsConfigured {
|
|
112
123
|
// it will process a fee
|
|
113
124
|
|
|
125
|
+
// Mock accountingContextOf for the decimals lookup in executePayout
|
|
126
|
+
mockExpect(
|
|
127
|
+
address(store),
|
|
128
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _noProject, _native)),
|
|
129
|
+
abi.encode(JBAccountingContext({token: _native, decimals: 0, currency: 0}))
|
|
130
|
+
);
|
|
131
|
+
|
|
114
132
|
// mock call to split hook supportsInterface
|
|
115
133
|
mockExpect(
|
|
116
134
|
address(_hook),
|
|
@@ -13,6 +13,8 @@ import {JBTokenAmount} from "../../../../src/structs/JBTokenAmount.sol";
|
|
|
13
13
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
14
14
|
import {JBMultiTerminalSetup} from "./JBMultiTerminalSetup.sol";
|
|
15
15
|
|
|
16
|
+
// Accounting context is now read from the store
|
|
17
|
+
|
|
16
18
|
contract TestExecuteProcessFee_Local is JBMultiTerminalSetup {
|
|
17
19
|
uint256 _projectId = 1;
|
|
18
20
|
uint256 _defaultAmount = 1e18;
|
|
@@ -28,11 +30,12 @@ contract TestExecuteProcessFee_Local is JBMultiTerminalSetup {
|
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
function _setAccountingContext(address token, uint8 decimals, uint32 currency) internal {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
// Mock the store to return this accounting context
|
|
34
|
+
mockExpect(
|
|
35
|
+
address(store),
|
|
36
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, token)),
|
|
37
|
+
abi.encode(JBAccountingContext({token: token, decimals: decimals, currency: currency}))
|
|
38
|
+
);
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
function test_WhenCallerIsNotItself() external {
|
|
@@ -7,7 +7,6 @@ import {IJBController} from "../../../../src/interfaces/IJBController.sol";
|
|
|
7
7
|
import {IJBDirectory} from "../../../../src/interfaces/IJBDirectory.sol";
|
|
8
8
|
import {IJBPayHook} from "../../../../src/interfaces/IJBPayHook.sol";
|
|
9
9
|
import {IJBRulesetApprovalHook} from "../../../../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
10
|
-
import {IJBRulesets} from "../../../../src/interfaces/IJBRulesets.sol";
|
|
11
10
|
import {IJBTerminal} from "../../../../src/interfaces/IJBTerminal.sol";
|
|
12
11
|
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
13
12
|
import {IJBTokens} from "../../../../src/interfaces/IJBTokens.sol";
|
|
@@ -17,7 +16,6 @@ import {JBAfterPayRecordedContext} from "../../../../src/structs/JBAfterPayRecor
|
|
|
17
16
|
import {JBPayHookSpecification} from "../../../../src/structs/JBPayHookSpecification.sol";
|
|
18
17
|
import {JBRuleset} from "../../../../src/structs/JBRuleset.sol";
|
|
19
18
|
import {JBTokenAmount} from "../../../../src/structs/JBTokenAmount.sol";
|
|
20
|
-
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
21
19
|
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
22
20
|
import {JBMultiTerminalSetup} from "./JBMultiTerminalSetup.sol";
|
|
23
21
|
|
|
@@ -60,23 +58,22 @@ contract TestPay_Local is JBMultiTerminalSetup {
|
|
|
60
58
|
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
61
59
|
});
|
|
62
60
|
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
basedOnId: 0,
|
|
68
|
-
start: 0,
|
|
69
|
-
duration: 0,
|
|
70
|
-
weight: 0,
|
|
71
|
-
weightCutPercent: 0,
|
|
72
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
73
|
-
metadata: 0
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(returnedRuleset));
|
|
61
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
62
|
+
mockExpect(
|
|
63
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
64
|
+
);
|
|
77
65
|
|
|
78
66
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
79
67
|
|
|
68
|
+
// Mock accountingContextOf for subsequent reads
|
|
69
|
+
mockExpect(
|
|
70
|
+
address(store),
|
|
71
|
+
abi.encodeCall(
|
|
72
|
+
IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, JBConstants.NATIVE_TOKEN)
|
|
73
|
+
),
|
|
74
|
+
abi.encode(_tokens[0])
|
|
75
|
+
);
|
|
76
|
+
|
|
80
77
|
_;
|
|
81
78
|
}
|
|
82
79
|
|
|
@@ -89,31 +86,25 @@ contract TestPay_Local is JBMultiTerminalSetup {
|
|
|
89
86
|
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
90
87
|
);
|
|
91
88
|
|
|
92
|
-
// mock call to token decimals
|
|
93
|
-
mockExpect(address(_mockToken), abi.encodeCall(IERC20Metadata.decimals, ()), abi.encode(6));
|
|
94
|
-
|
|
95
89
|
JBAccountingContext[] memory _tokens = new JBAccountingContext[](1);
|
|
96
90
|
_tokens[0] = JBAccountingContext({
|
|
97
91
|
token: address(_mockToken), decimals: 6, currency: uint32(uint160(address(_mockToken)))
|
|
98
92
|
});
|
|
99
93
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
basedOnId: 0,
|
|
105
|
-
start: 0,
|
|
106
|
-
duration: 0,
|
|
107
|
-
weight: 0,
|
|
108
|
-
weightCutPercent: 0,
|
|
109
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
110
|
-
metadata: 0
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(ruleset));
|
|
94
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
95
|
+
mockExpect(
|
|
96
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
97
|
+
);
|
|
114
98
|
|
|
115
99
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
116
100
|
|
|
101
|
+
// Mock accountingContextOf for subsequent reads
|
|
102
|
+
mockExpect(
|
|
103
|
+
address(store),
|
|
104
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, address(_mockToken))),
|
|
105
|
+
abi.encode(_tokens[0])
|
|
106
|
+
);
|
|
107
|
+
|
|
117
108
|
_;
|
|
118
109
|
}
|
|
119
110
|
|
|
@@ -254,6 +245,7 @@ contract TestPay_Local is JBMultiTerminalSetup {
|
|
|
254
245
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
255
246
|
token: address(_mockToken),
|
|
256
247
|
decimals: 6,
|
|
248
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
257
249
|
currency: uint32(_mockTokenCurrency),
|
|
258
250
|
value: _defaultAmount
|
|
259
251
|
});
|
|
@@ -441,8 +433,16 @@ contract TestPay_Local is JBMultiTerminalSetup {
|
|
|
441
433
|
function test_WhenTheProjectDNHAccountingContextForTheToken() external {
|
|
442
434
|
// it will revert TOKEN_NOT_ACCEPTED
|
|
443
435
|
|
|
436
|
+
// Mock totalBalanceOf (called before _acceptFundsFor)
|
|
444
437
|
mockExpect(address(tokens), abi.encodeCall(IJBTokens.totalBalanceOf, (_bene, _projectId)), abi.encode(0));
|
|
445
438
|
|
|
439
|
+
// Mock accountingContextOf to return empty context (token not accepted)
|
|
440
|
+
mockExpect(
|
|
441
|
+
address(store),
|
|
442
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _native)),
|
|
443
|
+
abi.encode(JBAccountingContext({token: address(0), decimals: 0, currency: 0}))
|
|
444
|
+
);
|
|
445
|
+
|
|
446
446
|
vm.expectRevert(abi.encodeWithSelector(JBMultiTerminal.JBMultiTerminal_TokenNotAccepted.selector, _native));
|
|
447
447
|
_terminal.pay{value: 1e18}({
|
|
448
448
|
projectId: _projectId,
|
|
@@ -463,8 +463,16 @@ contract TestPay_Local is JBMultiTerminalSetup {
|
|
|
463
463
|
function test_WhenTheTerminalsTokenEqNativeTokenAndMsgvalueEqZero() external {
|
|
464
464
|
// it will revert NO_MSG_VALUE_ALLOWED
|
|
465
465
|
|
|
466
|
+
// Mock totalBalanceOf (called before _acceptFundsFor)
|
|
466
467
|
mockExpect(address(tokens), abi.encodeCall(IJBTokens.totalBalanceOf, (_bene, _projectId)), abi.encode(0));
|
|
467
468
|
|
|
469
|
+
// Mock accountingContextOf to return empty context (token not accepted)
|
|
470
|
+
mockExpect(
|
|
471
|
+
address(store),
|
|
472
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _native)),
|
|
473
|
+
abi.encode(JBAccountingContext({token: address(0), decimals: 0, currency: 0}))
|
|
474
|
+
);
|
|
475
|
+
|
|
468
476
|
vm.expectRevert(abi.encodeWithSelector(JBMultiTerminal.JBMultiTerminal_TokenNotAccepted.selector, _native));
|
|
469
477
|
_terminal.pay{value: 0}({
|
|
470
478
|
projectId: _projectId,
|
|
@@ -5,7 +5,6 @@ import {JBMultiTerminal} from "../../../../src/JBMultiTerminal.sol";
|
|
|
5
5
|
import {IJBCashOutHook} from "../../../../src/interfaces/IJBCashOutHook.sol";
|
|
6
6
|
import {IJBDirectory} from "../../../../src/interfaces/IJBDirectory.sol";
|
|
7
7
|
import {IJBFeelessAddresses} from "../../../../src/interfaces/IJBFeelessAddresses.sol";
|
|
8
|
-
import {IJBRulesets} from "../../../../src/interfaces/IJBRulesets.sol";
|
|
9
8
|
import {IJBRulesetApprovalHook} from "../../../../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
10
9
|
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
11
10
|
import {JBConstants} from "../../../../src/libraries/JBConstants.sol";
|
|
@@ -32,34 +31,35 @@ contract TestPreviewCashOutFrom_Local is JBMultiTerminalSetup {
|
|
|
32
31
|
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
33
32
|
);
|
|
34
33
|
|
|
35
|
-
JBRuleset memory returnedRuleset = JBRuleset({
|
|
36
|
-
cycleNumber: 1,
|
|
37
|
-
id: 0,
|
|
38
|
-
basedOnId: 0,
|
|
39
|
-
start: 0,
|
|
40
|
-
duration: 0,
|
|
41
|
-
weight: 0,
|
|
42
|
-
weightCutPercent: 0,
|
|
43
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
44
|
-
metadata: 0
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(returnedRuleset));
|
|
48
|
-
|
|
49
34
|
JBAccountingContext[] memory contexts = new JBAccountingContext[](1);
|
|
50
35
|
contexts[0] = JBAccountingContext({token: token, decimals: decimals, currency: currency});
|
|
51
36
|
|
|
37
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
38
|
+
mockExpect(
|
|
39
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, contexts)), ""
|
|
40
|
+
);
|
|
41
|
+
|
|
52
42
|
vm.prank(address(this));
|
|
53
43
|
_terminal.addAccountingContextsFor(_projectId, contexts);
|
|
44
|
+
|
|
45
|
+
// Mock accountingContextOf for subsequent reads (not all code paths call it, so use mockCall only)
|
|
46
|
+
vm.mockCall(
|
|
47
|
+
address(store),
|
|
48
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, token)),
|
|
49
|
+
abi.encode(contexts[0])
|
|
50
|
+
);
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
function test_RevertsWhenTokenIsNotAccepted() external {
|
|
57
|
-
|
|
54
|
+
// previewCashOutFrom now delegates directly to the store without a token acceptance check,
|
|
55
|
+
// so it reverts during store computation (e.g. unmocked external call) rather than with TokenNotAccepted.
|
|
56
|
+
vm.expectRevert();
|
|
58
57
|
JBMultiTerminal(address(_terminal))
|
|
59
58
|
.previewCashOutFrom(_holder, _projectId, _cashOutCount, _token, _beneficiary, "");
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
function test_ReturnsRulesetAndCashOutPreviewValues() external {
|
|
62
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
63
63
|
_acceptToken(_token, 18, uint32(uint160(_token)));
|
|
64
64
|
|
|
65
65
|
JBRuleset memory ruleset = JBRuleset({
|
|
@@ -80,7 +80,8 @@ contract TestPreviewCashOutFrom_Local is JBMultiTerminalSetup {
|
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
JBAccountingContext memory accountingContext =
|
|
83
|
-
|
|
83
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
84
|
+
JBAccountingContext({token: _token, decimals: 18, currency: uint32(uint160(_token))});
|
|
84
85
|
JBAccountingContext[] memory accountingContexts = new JBAccountingContext[](1);
|
|
85
86
|
accountingContexts[0] = accountingContext;
|
|
86
87
|
|
|
@@ -92,7 +93,7 @@ contract TestPreviewCashOutFrom_Local is JBMultiTerminalSetup {
|
|
|
92
93
|
address(store),
|
|
93
94
|
abi.encodeCall(
|
|
94
95
|
IJBTerminalStore.previewCashOutFrom,
|
|
95
|
-
(_holder, _projectId, _cashOutCount, accountingContext,
|
|
96
|
+
(address(_terminal), _holder, _projectId, _cashOutCount, accountingContext.token, true, bytes(""))
|
|
96
97
|
),
|
|
97
98
|
abi.encode(ruleset, 999, 1234, specs)
|
|
98
99
|
);
|
|
@@ -27,21 +27,50 @@ contract TestPreviewPayFor_Local is JBMultiTerminalSetup {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
function _setAccountingContext(address token, uint8 decimals, uint32 currency) internal {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
// Mock the store to return this accounting context
|
|
31
|
+
mockExpect(
|
|
32
|
+
address(store),
|
|
33
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, token)),
|
|
34
|
+
abi.encode(JBAccountingContext({token: token, decimals: decimals, currency: currency}))
|
|
35
|
+
);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
function test_RevertsWhenTokenIsNotAccepted() external {
|
|
39
|
+
// Mock accountingContextOf to return empty context (token not accepted)
|
|
40
|
+
mockExpect(
|
|
41
|
+
address(store),
|
|
42
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _token)),
|
|
43
|
+
abi.encode(JBAccountingContext({token: address(0), decimals: 0, currency: 0}))
|
|
44
|
+
);
|
|
45
|
+
|
|
37
46
|
vm.prank(_payer);
|
|
38
47
|
vm.expectRevert(abi.encodeWithSelector(JBMultiTerminal.JBMultiTerminal_TokenNotAccepted.selector, _token));
|
|
39
48
|
JBMultiTerminal(address(_terminal)).previewPayFor(_projectId, _token, _amount, _beneficiary, "");
|
|
40
49
|
}
|
|
41
50
|
|
|
42
51
|
function test_ReturnsRulesetMintSplitAndHookSpecifications() external {
|
|
52
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
43
53
|
_setAccountingContext(_token, 18, uint32(uint160(_token)));
|
|
44
54
|
|
|
55
|
+
_mockPreviewPayFrom();
|
|
56
|
+
|
|
57
|
+
vm.prank(_payer);
|
|
58
|
+
(
|
|
59
|
+
JBRuleset memory previewRuleset,
|
|
60
|
+
uint256 beneficiaryTokenCount,
|
|
61
|
+
uint256 reservedTokenCount,
|
|
62
|
+
JBPayHookSpecification[] memory previewSpecs
|
|
63
|
+
) = JBMultiTerminal(address(_terminal)).previewPayFor(_projectId, _token, _amount, _beneficiary, "");
|
|
64
|
+
|
|
65
|
+
assertEq(previewRuleset.id, 1);
|
|
66
|
+
assertEq(beneficiaryTokenCount, 750);
|
|
67
|
+
assertEq(reservedTokenCount, 250);
|
|
68
|
+
assertEq(previewSpecs.length, 1);
|
|
69
|
+
assertEq(previewSpecs[0].amount, 123);
|
|
70
|
+
assertEq(previewSpecs[0].metadata, hex"1234");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function _mockPreviewPayFrom() internal {
|
|
45
74
|
JBRuleset memory ruleset = JBRuleset({
|
|
46
75
|
cycleNumber: 1,
|
|
47
76
|
id: 1,
|
|
@@ -59,11 +88,14 @@ contract TestPreviewPayFor_Local is JBMultiTerminalSetup {
|
|
|
59
88
|
JBPayHookSpecification({hook: IJBPayHook(makeAddr("hook")), noop: false, amount: 123, metadata: hex"1234"});
|
|
60
89
|
|
|
61
90
|
JBTokenAmount memory tokenAmount =
|
|
62
|
-
|
|
91
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
92
|
+
JBTokenAmount({token: _token, decimals: 18, currency: uint32(uint160(_token)), value: _amount});
|
|
63
93
|
|
|
64
94
|
mockExpect(
|
|
65
95
|
address(store),
|
|
66
|
-
abi.
|
|
96
|
+
abi.encodeWithSelector(
|
|
97
|
+
bytes4(0xdb6d7e03), address(_terminal), _payer, tokenAmount, _projectId, _beneficiary, bytes("")
|
|
98
|
+
),
|
|
67
99
|
abi.encode(ruleset, 1000, specs)
|
|
68
100
|
);
|
|
69
101
|
|
|
@@ -78,21 +110,5 @@ contract TestPreviewPayFor_Local is JBMultiTerminalSetup {
|
|
|
78
110
|
abi.encodeCall(IJBController.previewMintOf, (_projectId, 1000, true)),
|
|
79
111
|
abi.encode(750, 250)
|
|
80
112
|
);
|
|
81
|
-
|
|
82
|
-
vm.prank(_payer);
|
|
83
|
-
(
|
|
84
|
-
JBRuleset memory previewRuleset,
|
|
85
|
-
uint256 beneficiaryTokenCount,
|
|
86
|
-
uint256 reservedTokenCount,
|
|
87
|
-
JBPayHookSpecification[] memory previewSpecs
|
|
88
|
-
) = JBMultiTerminal(address(_terminal)).previewPayFor(_projectId, _token, _amount, _beneficiary, "");
|
|
89
|
-
|
|
90
|
-
assertEq(previewRuleset.id, ruleset.id);
|
|
91
|
-
assertEq(beneficiaryTokenCount, 750);
|
|
92
|
-
assertEq(reservedTokenCount, 250);
|
|
93
|
-
assertEq(previewSpecs.length, 1);
|
|
94
|
-
assertEq(address(previewSpecs[0].hook), address(specs[0].hook));
|
|
95
|
-
assertEq(previewSpecs[0].amount, specs[0].amount);
|
|
96
|
-
assertEq(previewSpecs[0].metadata, specs[0].metadata);
|
|
97
113
|
}
|
|
98
114
|
}
|
|
@@ -13,6 +13,7 @@ import {IJBSplits} from "../../../../src/interfaces/IJBSplits.sol";
|
|
|
13
13
|
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
14
14
|
import {IJBTokens} from "../../../../src/interfaces/IJBTokens.sol";
|
|
15
15
|
import {JBFees} from "../../../../src/libraries/JBFees.sol";
|
|
16
|
+
import {JBAccountingContext} from "../../../../src/structs/JBAccountingContext.sol";
|
|
16
17
|
import {JBFee} from "../../../../src/structs/JBFee.sol";
|
|
17
18
|
import {JBPayHookSpecification} from "../../../../src/structs/JBPayHookSpecification.sol";
|
|
18
19
|
import {JBRuleset} from "../../../../src/structs/JBRuleset.sol";
|
|
@@ -65,16 +66,17 @@ contract TestProcessHeldFeesOf_Local is JBTest {
|
|
|
65
66
|
address _beneficiary = makeAddr("beneficiary");
|
|
66
67
|
|
|
67
68
|
function _setAccountingContext(uint256 projectId, address token, uint8 decimals, uint32 currency) internal {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
// Mock the store to return this accounting context
|
|
70
|
+
mockExpect(
|
|
71
|
+
address(store),
|
|
72
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), projectId, token)),
|
|
73
|
+
abi.encode(JBAccountingContext({token: token, decimals: decimals, currency: currency}))
|
|
74
|
+
);
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
function setUp() public {
|
|
75
|
-
// Constructor will call to find directory
|
|
78
|
+
// Constructor will call to find directory from the terminal store
|
|
76
79
|
mockExpect(address(store), abi.encodeCall(IJBTerminalStore.DIRECTORY, ()), abi.encode(address(directory)));
|
|
77
|
-
mockExpect(address(store), abi.encodeCall(IJBTerminalStore.RULESETS, ()), abi.encode(address(rulesets)));
|
|
78
80
|
|
|
79
81
|
_terminal = new ForTest_JBMultiTerminal(
|
|
80
82
|
feelessAddresses, permissions, projects, splits, store, tokens, permit2, trustedForwarder
|
|
@@ -127,6 +129,7 @@ contract TestProcessHeldFeesOf_Local is JBTest {
|
|
|
127
129
|
uint256 expectedFeeAmount = JBFees.feeAmountFrom({amountBeforeFee: heldAmount, feePercent: _terminal.FEE()});
|
|
128
130
|
|
|
129
131
|
// Set up accounting context for the fee beneficiary project (project 1) so _pay can build the token amount.
|
|
132
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
130
133
|
_setAccountingContext(_feeProjectId, _mockToken, 0, uint32(uint160(_mockToken)));
|
|
131
134
|
|
|
132
135
|
// Mock the directory call to find the fee terminal - return _terminal itself so it uses internal _pay
|
|
@@ -47,7 +47,7 @@ contract TestSendPayoutsOf_Local is JBMultiTerminalSetup {
|
|
|
47
47
|
// record payout mock call
|
|
48
48
|
mockExpect(
|
|
49
49
|
address(store),
|
|
50
|
-
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext, 0, 0)),
|
|
50
|
+
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext.token, 0, 0)),
|
|
51
51
|
abi.encode(returnedRuleset, 0)
|
|
52
52
|
);
|
|
53
53
|
|
|
@@ -86,7 +86,7 @@ contract TestSendPayoutsOf_Local is JBMultiTerminalSetup {
|
|
|
86
86
|
// record payout mock call
|
|
87
87
|
mockExpect(
|
|
88
88
|
address(store),
|
|
89
|
-
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext, 0, 0)),
|
|
89
|
+
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext.token, 0, 0)),
|
|
90
90
|
abi.encode(returnedRuleset, 0)
|
|
91
91
|
);
|
|
92
92
|
|
|
@@ -134,7 +134,7 @@ contract TestSendPayoutsOf_Local is JBMultiTerminalSetup {
|
|
|
134
134
|
// record payout mock call
|
|
135
135
|
mockExpect(
|
|
136
136
|
address(store),
|
|
137
|
-
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext, 0, 0)),
|
|
137
|
+
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext.token, 0, 0)),
|
|
138
138
|
abi.encode(returnedRuleset, 0)
|
|
139
139
|
);
|
|
140
140
|
|
|
@@ -204,7 +204,7 @@ contract TestSendPayoutsOf_Local is JBMultiTerminalSetup {
|
|
|
204
204
|
// record payout mock call
|
|
205
205
|
mockExpect(
|
|
206
206
|
address(store),
|
|
207
|
-
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext, 0, 100)),
|
|
207
|
+
abi.encodeCall(IJBTerminalStore.recordPayoutFor, (_projectId, mockTokenContext.token, 0, 100)),
|
|
208
208
|
abi.encode(returnedRuleset, 100)
|
|
209
209
|
);
|
|
210
210
|
|