@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
|
@@ -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(
|
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
4
|
import {IJBDirectory} from "../../../../src/interfaces/IJBDirectory.sol";
|
|
5
|
-
import {
|
|
6
|
-
import {IJBRulesets} from "../../../../src/interfaces/IJBRulesets.sol";
|
|
5
|
+
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
7
6
|
import {JBAccountingContext} from "../../../../src/structs/JBAccountingContext.sol";
|
|
8
|
-
import {JBRuleset} from "../../../../src/structs/JBRuleset.sol";
|
|
9
|
-
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
10
7
|
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
11
8
|
import {JBMultiTerminalSetup} from "./JBMultiTerminalSetup.sol";
|
|
12
9
|
|
|
@@ -33,40 +30,42 @@ contract TestAccountingContextsOf_Local is JBMultiTerminalSetup {
|
|
|
33
30
|
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
34
31
|
);
|
|
35
32
|
|
|
36
|
-
// mock call to tokens decimals()
|
|
37
|
-
mockExpect(_usdc, abi.encodeCall(IERC20Metadata.decimals, ()), abi.encode(6));
|
|
38
|
-
|
|
39
|
-
// setup: return data
|
|
40
|
-
JBRuleset memory ruleset = JBRuleset({
|
|
41
|
-
cycleNumber: 1,
|
|
42
|
-
id: 0,
|
|
43
|
-
basedOnId: 0,
|
|
44
|
-
start: 0,
|
|
45
|
-
duration: 0,
|
|
46
|
-
weight: 0,
|
|
47
|
-
weightCutPercent: 0,
|
|
48
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
49
|
-
metadata: 0
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// mock call to rulesets currentOf returning 0 to bypass ruleset checking
|
|
53
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(ruleset));
|
|
54
|
-
|
|
55
33
|
// call params
|
|
56
34
|
JBAccountingContext[] memory _tokens = new JBAccountingContext[](1);
|
|
57
35
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
58
36
|
_tokens[0] = JBAccountingContext({token: _usdc, decimals: 6, currency: uint32(uint160(_usdc))});
|
|
59
37
|
|
|
38
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
39
|
+
mockExpect(
|
|
40
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
41
|
+
);
|
|
42
|
+
|
|
60
43
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
61
44
|
|
|
45
|
+
// Mock the store to return all contexts when queried
|
|
46
|
+
mockExpect(
|
|
47
|
+
address(store),
|
|
48
|
+
abi.encodeCall(IJBTerminalStore.accountingContextsOf, (address(_terminal), _projectId)),
|
|
49
|
+
abi.encode(_tokens)
|
|
50
|
+
);
|
|
51
|
+
|
|
62
52
|
JBAccountingContext[] memory _storedContexts = _terminal.accountingContextsOf(_projectId);
|
|
63
53
|
assertEq(_storedContexts[0].currency, _usdcCurrency);
|
|
64
54
|
assertEq(_storedContexts[0].token, _usdc);
|
|
65
55
|
assertEq(_storedContexts[0].decimals, 6);
|
|
66
56
|
}
|
|
67
57
|
|
|
68
|
-
function test_WhenAccountingContextsAreNotSet() external
|
|
58
|
+
function test_WhenAccountingContextsAreNotSet() external {
|
|
69
59
|
// it will return an empty array
|
|
60
|
+
|
|
61
|
+
// Mock the store to return empty array
|
|
62
|
+
JBAccountingContext[] memory _empty = new JBAccountingContext[](0);
|
|
63
|
+
mockExpect(
|
|
64
|
+
address(store),
|
|
65
|
+
abi.encodeCall(IJBTerminalStore.accountingContextsOf, (address(_terminal), _projectId)),
|
|
66
|
+
abi.encode(_empty)
|
|
67
|
+
);
|
|
68
|
+
|
|
70
69
|
JBAccountingContext[] memory _storedContexts = _terminal.accountingContextsOf(_projectId);
|
|
71
70
|
assertEq(_storedContexts.length, 0);
|
|
72
71
|
}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {JBTerminalStore} from "../../../../src/JBTerminalStore.sol";
|
|
5
5
|
import {IJBDirectory} from "../../../../src/interfaces/IJBDirectory.sol";
|
|
6
|
-
import {
|
|
7
|
-
import {IJBRulesets} from "../../../../src/interfaces/IJBRulesets.sol";
|
|
6
|
+
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
8
7
|
import {JBConstants} from "../../../../src/libraries/JBConstants.sol";
|
|
9
8
|
import {JBAccountingContext} from "../../../../src/structs/JBAccountingContext.sol";
|
|
10
|
-
import {JBRuleset} from "../../../../src/structs/JBRuleset.sol";
|
|
11
|
-
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
12
9
|
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
13
10
|
import {JBMultiTerminalSetup} from "./JBMultiTerminalSetup.sol";
|
|
14
11
|
|
|
@@ -43,44 +40,20 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
43
40
|
function test_GivenTheContextIsAlreadySet() external whenCallerIsPermissioned {
|
|
44
41
|
// it will revert ACCOUNTING_CONTEXT_ALREADY_SET
|
|
45
42
|
|
|
46
|
-
// Accounting Context to set
|
|
47
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
48
|
-
JBAccountingContext memory _context =
|
|
49
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
50
|
-
JBAccountingContext({token: _usdc, decimals: 18, currency: uint32(_usdcCurrency)});
|
|
51
|
-
|
|
52
|
-
// Find the storage slot
|
|
53
|
-
bytes32 contextSlot = keccak256(abi.encode(_projectId, uint256(0)));
|
|
54
|
-
bytes32 slot = keccak256(abi.encode(_usdc, contextSlot));
|
|
55
|
-
|
|
56
|
-
// Set storage
|
|
57
|
-
vm.store(address(_terminal), slot, bytes32(abi.encode(_context)));
|
|
58
|
-
|
|
59
|
-
// setup: return data
|
|
60
|
-
JBRuleset memory ruleset = JBRuleset({
|
|
61
|
-
cycleNumber: 1,
|
|
62
|
-
id: 0,
|
|
63
|
-
basedOnId: 0,
|
|
64
|
-
start: 0,
|
|
65
|
-
duration: 0,
|
|
66
|
-
weight: 0,
|
|
67
|
-
weightCutPercent: 0,
|
|
68
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
69
|
-
metadata: 0
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(ruleset));
|
|
73
|
-
|
|
74
|
-
JBAccountingContext memory _storedContext = _terminal.accountingContextForTokenOf(_projectId, _usdc);
|
|
75
|
-
assertEq(_storedContext.token, _usdc);
|
|
76
|
-
|
|
77
43
|
// call params
|
|
78
44
|
JBAccountingContext[] memory _tokens = new JBAccountingContext[](1);
|
|
79
45
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
80
46
|
_tokens[0] = JBAccountingContext({token: _usdc, decimals: 6, currency: uint32(uint160(_usdc))});
|
|
81
47
|
|
|
48
|
+
// Mock recordAccountingContextOf to revert with AccountingContextAlreadySet
|
|
49
|
+
vm.mockCallRevert(
|
|
50
|
+
address(store),
|
|
51
|
+
abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)),
|
|
52
|
+
abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_AccountingContextAlreadySet.selector, _usdc)
|
|
53
|
+
);
|
|
54
|
+
|
|
82
55
|
vm.expectRevert(
|
|
83
|
-
abi.encodeWithSelector(
|
|
56
|
+
abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_AccountingContextAlreadySet.selector, _usdc)
|
|
84
57
|
);
|
|
85
58
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
86
59
|
}
|
|
@@ -88,32 +61,25 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
88
61
|
function test_GivenHappyPathERC20() external whenCallerIsPermissioned {
|
|
89
62
|
// it will set the context and emit SetAccountingContext
|
|
90
63
|
|
|
91
|
-
// mock call to tokens decimals()
|
|
92
|
-
mockExpect(_usdc, abi.encodeCall(IERC20Metadata.decimals, ()), abi.encode(6));
|
|
93
|
-
|
|
94
|
-
// setup: return data
|
|
95
|
-
JBRuleset memory ruleset = JBRuleset({
|
|
96
|
-
cycleNumber: 1,
|
|
97
|
-
id: 0,
|
|
98
|
-
basedOnId: 0,
|
|
99
|
-
start: 0,
|
|
100
|
-
duration: 0,
|
|
101
|
-
weight: 0,
|
|
102
|
-
weightCutPercent: 0,
|
|
103
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
104
|
-
metadata: 0
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// mock call to rulesets currentOf returning 0 to bypass ruleset checking
|
|
108
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(ruleset));
|
|
109
|
-
|
|
110
64
|
// call params
|
|
111
65
|
JBAccountingContext[] memory _tokens = new JBAccountingContext[](1);
|
|
112
66
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
113
67
|
_tokens[0] = JBAccountingContext({token: _usdc, decimals: 6, currency: uint32(uint160(_usdc))});
|
|
114
68
|
|
|
69
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
70
|
+
mockExpect(
|
|
71
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
72
|
+
);
|
|
73
|
+
|
|
115
74
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
116
75
|
|
|
76
|
+
// Mock the store to return the context when queried
|
|
77
|
+
mockExpect(
|
|
78
|
+
address(store),
|
|
79
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _usdc)),
|
|
80
|
+
abi.encode(_tokens[0])
|
|
81
|
+
);
|
|
82
|
+
|
|
117
83
|
JBAccountingContext memory _storedContext = _terminal.accountingContextForTokenOf(_projectId, _usdc);
|
|
118
84
|
assertEq(_storedContext.token, _usdc);
|
|
119
85
|
assertEq(_storedContext.decimals, 6);
|
|
@@ -128,25 +94,22 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
128
94
|
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
129
95
|
});
|
|
130
96
|
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
cycleNumber: 1,
|
|
136
|
-
id: 0,
|
|
137
|
-
basedOnId: 0,
|
|
138
|
-
start: 0,
|
|
139
|
-
duration: 0,
|
|
140
|
-
weight: 0,
|
|
141
|
-
weightCutPercent: 0,
|
|
142
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
143
|
-
metadata: 0
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(ruleset));
|
|
97
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
98
|
+
mockExpect(
|
|
99
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
100
|
+
);
|
|
147
101
|
|
|
148
102
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
149
103
|
|
|
104
|
+
// Mock the store to return the context when queried
|
|
105
|
+
mockExpect(
|
|
106
|
+
address(store),
|
|
107
|
+
abi.encodeCall(
|
|
108
|
+
IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, JBConstants.NATIVE_TOKEN)
|
|
109
|
+
),
|
|
110
|
+
abi.encode(_tokens[0])
|
|
111
|
+
);
|
|
112
|
+
|
|
150
113
|
JBAccountingContext memory _storedContext =
|
|
151
114
|
_terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN);
|
|
152
115
|
assertEq(_storedContext.token, JBConstants.NATIVE_TOKEN);
|
|
@@ -173,23 +136,22 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
173
136
|
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
174
137
|
});
|
|
175
138
|
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
basedOnId: 0,
|
|
181
|
-
start: 0,
|
|
182
|
-
duration: 0,
|
|
183
|
-
weight: 0,
|
|
184
|
-
weightCutPercent: 0,
|
|
185
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
186
|
-
metadata: 0
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.currentOf, (_projectId)), abi.encode(ruleset));
|
|
139
|
+
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
140
|
+
mockExpect(
|
|
141
|
+
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
142
|
+
);
|
|
190
143
|
|
|
191
144
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
192
145
|
|
|
146
|
+
// Mock the store to return the context when queried
|
|
147
|
+
mockExpect(
|
|
148
|
+
address(store),
|
|
149
|
+
abi.encodeCall(
|
|
150
|
+
IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, JBConstants.NATIVE_TOKEN)
|
|
151
|
+
),
|
|
152
|
+
abi.encode(_tokens[0])
|
|
153
|
+
);
|
|
154
|
+
|
|
193
155
|
JBAccountingContext memory _storedContext =
|
|
194
156
|
_terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN);
|
|
195
157
|
assertEq(_storedContext.token, JBConstants.NATIVE_TOKEN);
|
|
@@ -216,18 +178,19 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
216
178
|
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
217
179
|
});
|
|
218
180
|
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
181
|
+
// Mock recordAccountingContextOf to revert with AddingAccountingContextNotAllowed (validation now in store)
|
|
182
|
+
vm.mockCallRevert(
|
|
183
|
+
address(store),
|
|
184
|
+
abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)),
|
|
185
|
+
abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_AddingAccountingContextNotAllowed.selector)
|
|
186
|
+
);
|
|
224
187
|
|
|
225
|
-
vm.expectRevert(
|
|
188
|
+
vm.expectRevert(JBTerminalStore.JBTerminalStore_AddingAccountingContextNotAllowed.selector);
|
|
226
189
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
227
190
|
}
|
|
228
191
|
|
|
229
192
|
function test_WhenCurrencyIsNativeButDecimalsDNEQ18() external {
|
|
230
|
-
// it will revert
|
|
193
|
+
// it will revert JBTerminalStore_AccountingContextDecimalsMismatch
|
|
231
194
|
|
|
232
195
|
// mock call to JBProjects ownerOf(_projectId)
|
|
233
196
|
bytes memory _projectsCall = abi.encodeCall(IERC721.ownerOf, (_projectId));
|
|
@@ -247,18 +210,19 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
247
210
|
currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
248
211
|
});
|
|
249
212
|
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
213
|
+
// Mock recordAccountingContextOf to revert with DecimalsMismatch (validation now in store)
|
|
214
|
+
vm.mockCallRevert(
|
|
215
|
+
address(store),
|
|
216
|
+
abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)),
|
|
217
|
+
abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_AccountingContextDecimalsMismatch.selector)
|
|
218
|
+
);
|
|
255
219
|
|
|
256
|
-
vm.expectRevert(
|
|
220
|
+
vm.expectRevert(JBTerminalStore.JBTerminalStore_AccountingContextDecimalsMismatch.selector);
|
|
257
221
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
258
222
|
}
|
|
259
223
|
|
|
260
224
|
function test_WhenTokenDecimalsDoesNotMatchAccountingContext() external {
|
|
261
|
-
// it will revert
|
|
225
|
+
// it will revert JBTerminalStore_AccountingContextDecimalsMismatch
|
|
262
226
|
|
|
263
227
|
// mock call to JBProjects ownerOf(_projectId)
|
|
264
228
|
bytes memory _projectsCall = abi.encodeCall(IERC721.ownerOf, (_projectId));
|
|
@@ -281,21 +245,19 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
281
245
|
currency: uint32(uint160(someToken))
|
|
282
246
|
});
|
|
283
247
|
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// mock token call
|
|
291
|
-
mockExpect(address(someToken), abi.encodeCall(IERC20Metadata.decimals, ()), abi.encode(18));
|
|
248
|
+
// Mock recordAccountingContextOf to revert with DecimalsMismatch (validation now in store)
|
|
249
|
+
vm.mockCallRevert(
|
|
250
|
+
address(store),
|
|
251
|
+
abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)),
|
|
252
|
+
abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_AccountingContextDecimalsMismatch.selector)
|
|
253
|
+
);
|
|
292
254
|
|
|
293
|
-
vm.expectRevert(
|
|
255
|
+
vm.expectRevert(JBTerminalStore.JBTerminalStore_AccountingContextDecimalsMismatch.selector);
|
|
294
256
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
295
257
|
}
|
|
296
258
|
|
|
297
259
|
function test_WhenCurrencyEQZero() external {
|
|
298
|
-
// it will revert
|
|
260
|
+
// it will revert JBTerminalStore_ZeroAccountingContextCurrency
|
|
299
261
|
|
|
300
262
|
// mock call to JBProjects ownerOf(_projectId)
|
|
301
263
|
bytes memory _projectsCall = abi.encodeCall(IERC721.ownerOf, (_projectId));
|
|
@@ -314,16 +276,14 @@ contract TestAddAccountingContextsFor_Local is JBMultiTerminalSetup {
|
|
|
314
276
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
315
277
|
_tokens[0] = JBAccountingContext({token: someToken, decimals: 18, currency: uint32(uint160(0))});
|
|
316
278
|
|
|
317
|
-
//
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
// mock token call
|
|
324
|
-
mockExpect(address(someToken), abi.encodeCall(IERC20Metadata.decimals, ()), abi.encode(18));
|
|
279
|
+
// Mock recordAccountingContextOf to revert with ZeroAccountingContextCurrency (validation now in store)
|
|
280
|
+
vm.mockCallRevert(
|
|
281
|
+
address(store),
|
|
282
|
+
abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)),
|
|
283
|
+
abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_ZeroAccountingContextCurrency.selector)
|
|
284
|
+
);
|
|
325
285
|
|
|
326
|
-
vm.expectRevert(
|
|
286
|
+
vm.expectRevert(JBTerminalStore.JBTerminalStore_ZeroAccountingContextCurrency.selector);
|
|
327
287
|
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
328
288
|
}
|
|
329
289
|
}
|
|
@@ -55,12 +55,12 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup {
|
|
|
55
55
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
56
56
|
JBAccountingContext({token: _native, decimals: 18, currency: uint32(_nativeCurrency)});
|
|
57
57
|
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
// Mock the store to return this accounting context
|
|
59
|
+
mockExpect(
|
|
60
|
+
address(store),
|
|
61
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _native)),
|
|
62
|
+
abi.encode(_context)
|
|
63
|
+
);
|
|
64
64
|
|
|
65
65
|
JBAccountingContext memory _storedContext = _terminal.accountingContextForTokenOf(_projectId, _native);
|
|
66
66
|
assertEq(_storedContext.token, _native);
|
|
@@ -75,18 +75,18 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup {
|
|
|
75
75
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
76
76
|
JBAccountingContext({token: _native, decimals: 18, currency: uint32(_nativeCurrency)});
|
|
77
77
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
// Mock the store to return this accounting context
|
|
79
|
+
mockExpect(
|
|
80
|
+
address(store),
|
|
81
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _native)),
|
|
82
|
+
abi.encode(_context)
|
|
83
|
+
);
|
|
84
84
|
|
|
85
85
|
JBAccountingContext memory _storedContext = _terminal.accountingContextForTokenOf(_projectId, _native);
|
|
86
86
|
assertEq(_storedContext.token, _native);
|
|
87
87
|
|
|
88
|
-
// Find the storage slot for fees array (_heldFeesOf is at storage slot
|
|
89
|
-
bytes32 feeSlot = keccak256(abi.encode(_projectId, uint256(
|
|
88
|
+
// Find the storage slot for fees array (_heldFeesOf is at storage slot 1)
|
|
89
|
+
bytes32 feeSlot = keccak256(abi.encode(_projectId, uint256(1)));
|
|
90
90
|
bytes32 slotForArrayLength = keccak256(abi.encode(_native, feeSlot));
|
|
91
91
|
|
|
92
92
|
// Set the length of the fees array in the storage slot
|
|
@@ -223,6 +223,13 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup {
|
|
|
223
223
|
function test_WhenTheProjectDNHAccountingContextForTheToken() external {
|
|
224
224
|
// it will revert TOKEN_NOT_ACCEPTED
|
|
225
225
|
|
|
226
|
+
// Mock accountingContextOf to return empty context (token not accepted)
|
|
227
|
+
mockExpect(
|
|
228
|
+
address(store),
|
|
229
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _native)),
|
|
230
|
+
abi.encode(JBAccountingContext({token: address(0), decimals: 0, currency: 0}))
|
|
231
|
+
);
|
|
232
|
+
|
|
226
233
|
vm.expectRevert(abi.encodeWithSelector(JBMultiTerminal.JBMultiTerminal_TokenNotAccepted.selector, _native));
|
|
227
234
|
|
|
228
235
|
_terminal.addToBalanceOf{value: payAmount}({
|
|
@@ -244,12 +251,12 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup {
|
|
|
244
251
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
245
252
|
JBAccountingContext({token: _usdc, decimals: 18, currency: uint32(_usdcCurrency)});
|
|
246
253
|
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
254
|
+
// Mock the store to return this accounting context
|
|
255
|
+
mockExpect(
|
|
256
|
+
address(store),
|
|
257
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _usdc)),
|
|
258
|
+
abi.encode(_context)
|
|
259
|
+
);
|
|
253
260
|
|
|
254
261
|
JBAccountingContext memory _storedContext = _terminal.accountingContextForTokenOf(_projectId, _usdc);
|
|
255
262
|
assertEq(_storedContext.token, _usdc);
|
|
@@ -273,12 +280,12 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup {
|
|
|
273
280
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
274
281
|
JBAccountingContext({token: _usdc, decimals: 18, currency: uint32(_usdcCurrency)});
|
|
275
282
|
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
283
|
+
// Mock the store to return this accounting context
|
|
284
|
+
mockExpect(
|
|
285
|
+
address(store),
|
|
286
|
+
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, _usdc)),
|
|
287
|
+
abi.encode(_context)
|
|
288
|
+
);
|
|
282
289
|
|
|
283
290
|
JBAccountingContext memory _storedContext = _terminal.accountingContextForTokenOf(_projectId, _usdc);
|
|
284
291
|
assertEq(_storedContext.token, _usdc);
|