@bananapus/router-terminal-v6 0.0.1
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/LICENSE +21 -0
- package/README.md +145 -0
- package/SKILLS.md +101 -0
- package/foundry.toml +22 -0
- package/package.json +30 -0
- package/script/Deploy.s.sol +130 -0
- package/script/helpers/RouterTerminalDeploymentLib.sol +76 -0
- package/slither-ci.config.json +10 -0
- package/src/JBRouterTerminal.sol +1355 -0
- package/src/JBRouterTerminalRegistry.sol +466 -0
- package/src/interfaces/IJBRouterTerminal.sol +45 -0
- package/src/interfaces/IJBRouterTerminalRegistry.sol +62 -0
- package/src/interfaces/IWETH9.sol +13 -0
- package/src/libraries/JBSwapLib.sol +159 -0
- package/src/structs/PoolInfo.sol +14 -0
- package/test/RouterTerminal.t.sol +865 -0
- package/test/RouterTerminalRegistry.t.sol +333 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.26;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Test.sol";
|
|
5
|
+
|
|
6
|
+
import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
7
|
+
import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
8
|
+
import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
|
|
9
|
+
import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
10
|
+
import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
11
|
+
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
12
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
13
|
+
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
14
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
15
|
+
import {IPermit2} from "@uniswap/permit2/src/interfaces/IPermit2.sol";
|
|
16
|
+
|
|
17
|
+
import {JBRouterTerminalRegistry} from "../src/JBRouterTerminalRegistry.sol";
|
|
18
|
+
import {IJBRouterTerminalRegistry} from "../src/interfaces/IJBRouterTerminalRegistry.sol";
|
|
19
|
+
|
|
20
|
+
contract RouterTerminalRegistryTest is Test {
|
|
21
|
+
JBRouterTerminalRegistry registry;
|
|
22
|
+
|
|
23
|
+
// Mocked dependencies.
|
|
24
|
+
IJBPermissions permissions = IJBPermissions(makeAddr("permissions"));
|
|
25
|
+
IJBProjects projects = IJBProjects(makeAddr("projects"));
|
|
26
|
+
IPermit2 permit2 = IPermit2(makeAddr("permit2"));
|
|
27
|
+
address owner = makeAddr("owner");
|
|
28
|
+
address trustedForwarder = makeAddr("trustedForwarder");
|
|
29
|
+
|
|
30
|
+
// Mocked terminals.
|
|
31
|
+
IJBTerminal terminalA = IJBTerminal(makeAddr("terminalA"));
|
|
32
|
+
IJBTerminal terminalB = IJBTerminal(makeAddr("terminalB"));
|
|
33
|
+
|
|
34
|
+
// Test constants.
|
|
35
|
+
uint256 projectId = 1;
|
|
36
|
+
address projectOwner = makeAddr("projectOwner");
|
|
37
|
+
|
|
38
|
+
function setUp() public {
|
|
39
|
+
registry = new JBRouterTerminalRegistry(permissions, projects, permit2, owner, trustedForwarder);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
43
|
+
// Constructor / immutables
|
|
44
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
function test_constructor() public view {
|
|
47
|
+
assertEq(address(registry.PROJECTS()), address(projects));
|
|
48
|
+
assertEq(address(registry.PERMIT2()), address(permit2));
|
|
49
|
+
assertEq(address(registry.defaultTerminal()), address(0));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
53
|
+
// allowTerminal / disallowTerminal
|
|
54
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
function test_allowTerminal() public {
|
|
57
|
+
vm.prank(owner);
|
|
58
|
+
registry.allowTerminal(terminalA);
|
|
59
|
+
|
|
60
|
+
assertTrue(registry.isTerminalAllowed(terminalA));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function test_allowTerminal_revertsIfNotOwner() public {
|
|
64
|
+
vm.expectRevert();
|
|
65
|
+
registry.allowTerminal(terminalA);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function test_disallowTerminal() public {
|
|
69
|
+
vm.startPrank(owner);
|
|
70
|
+
registry.allowTerminal(terminalA);
|
|
71
|
+
registry.disallowTerminal(terminalA);
|
|
72
|
+
vm.stopPrank();
|
|
73
|
+
|
|
74
|
+
assertFalse(registry.isTerminalAllowed(terminalA));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function test_disallowTerminal_clearsDefault() public {
|
|
78
|
+
vm.startPrank(owner);
|
|
79
|
+
registry.setDefaultTerminal(terminalA);
|
|
80
|
+
registry.disallowTerminal(terminalA);
|
|
81
|
+
vm.stopPrank();
|
|
82
|
+
|
|
83
|
+
assertEq(address(registry.defaultTerminal()), address(0));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
87
|
+
// setDefaultTerminal
|
|
88
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
function test_setDefaultTerminal() public {
|
|
91
|
+
vm.prank(owner);
|
|
92
|
+
registry.setDefaultTerminal(terminalA);
|
|
93
|
+
|
|
94
|
+
assertEq(address(registry.defaultTerminal()), address(terminalA));
|
|
95
|
+
assertTrue(registry.isTerminalAllowed(terminalA));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function test_setDefaultTerminal_revertsIfNotOwner() public {
|
|
99
|
+
vm.expectRevert();
|
|
100
|
+
registry.setDefaultTerminal(terminalA);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
104
|
+
// terminalOf
|
|
105
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
function test_terminalOf_fallsBackToDefault() public {
|
|
108
|
+
vm.prank(owner);
|
|
109
|
+
registry.setDefaultTerminal(terminalA);
|
|
110
|
+
|
|
111
|
+
assertEq(address(registry.terminalOf(projectId)), address(terminalA));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function test_terminalOf_returnsProjectSpecific() public {
|
|
115
|
+
vm.prank(owner);
|
|
116
|
+
registry.setDefaultTerminal(terminalA);
|
|
117
|
+
|
|
118
|
+
// Allow terminalB and set it for the project.
|
|
119
|
+
vm.prank(owner);
|
|
120
|
+
registry.allowTerminal(terminalB);
|
|
121
|
+
|
|
122
|
+
// Mock the project owner.
|
|
123
|
+
vm.mockCall(address(projects), abi.encodeCall(IERC721.ownerOf, (projectId)), abi.encode(projectOwner));
|
|
124
|
+
// Mock the permission check.
|
|
125
|
+
vm.mockCall(
|
|
126
|
+
address(permissions),
|
|
127
|
+
abi.encodeWithSignature(
|
|
128
|
+
"hasPermission(address,address,uint256,uint256,bool,bool)",
|
|
129
|
+
projectOwner,
|
|
130
|
+
projectOwner,
|
|
131
|
+
projectId,
|
|
132
|
+
JBPermissionIds.SET_ROUTER_TERMINAL,
|
|
133
|
+
true,
|
|
134
|
+
true
|
|
135
|
+
),
|
|
136
|
+
abi.encode(true)
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
vm.prank(projectOwner);
|
|
140
|
+
registry.setTerminalFor(projectId, terminalB);
|
|
141
|
+
|
|
142
|
+
assertEq(address(registry.terminalOf(projectId)), address(terminalB));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
146
|
+
// setTerminalFor
|
|
147
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
function test_setTerminalFor_revertsIfNotAllowed() public {
|
|
150
|
+
// Mock the project owner.
|
|
151
|
+
vm.mockCall(address(projects), abi.encodeCall(IERC721.ownerOf, (projectId)), abi.encode(projectOwner));
|
|
152
|
+
vm.mockCall(
|
|
153
|
+
address(permissions),
|
|
154
|
+
abi.encodeWithSignature(
|
|
155
|
+
"hasPermission(address,address,uint256,uint256,bool,bool)",
|
|
156
|
+
projectOwner,
|
|
157
|
+
projectOwner,
|
|
158
|
+
projectId,
|
|
159
|
+
JBPermissionIds.SET_ROUTER_TERMINAL,
|
|
160
|
+
true,
|
|
161
|
+
true
|
|
162
|
+
),
|
|
163
|
+
abi.encode(true)
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
vm.prank(projectOwner);
|
|
167
|
+
vm.expectRevert(
|
|
168
|
+
abi.encodeWithSelector(
|
|
169
|
+
JBRouterTerminalRegistry.JBRouterTerminalRegistry_TerminalNotAllowed.selector, terminalA
|
|
170
|
+
)
|
|
171
|
+
);
|
|
172
|
+
registry.setTerminalFor(projectId, terminalA);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function test_setTerminalFor_revertsIfLocked() public {
|
|
176
|
+
// Set up: allow terminal, set it, lock it.
|
|
177
|
+
vm.prank(owner);
|
|
178
|
+
registry.allowTerminal(terminalA);
|
|
179
|
+
|
|
180
|
+
vm.mockCall(address(projects), abi.encodeCall(IERC721.ownerOf, (projectId)), abi.encode(projectOwner));
|
|
181
|
+
vm.mockCall(
|
|
182
|
+
address(permissions),
|
|
183
|
+
abi.encodeWithSignature(
|
|
184
|
+
"hasPermission(address,address,uint256,uint256,bool,bool)",
|
|
185
|
+
projectOwner,
|
|
186
|
+
projectOwner,
|
|
187
|
+
projectId,
|
|
188
|
+
JBPermissionIds.SET_ROUTER_TERMINAL,
|
|
189
|
+
true,
|
|
190
|
+
true
|
|
191
|
+
),
|
|
192
|
+
abi.encode(true)
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
vm.prank(projectOwner);
|
|
196
|
+
registry.setTerminalFor(projectId, terminalA);
|
|
197
|
+
|
|
198
|
+
vm.prank(projectOwner);
|
|
199
|
+
registry.lockTerminalFor(projectId);
|
|
200
|
+
|
|
201
|
+
// Try to change.
|
|
202
|
+
vm.prank(projectOwner);
|
|
203
|
+
vm.expectRevert(
|
|
204
|
+
abi.encodeWithSelector(JBRouterTerminalRegistry.JBRouterTerminalRegistry_TerminalLocked.selector, projectId)
|
|
205
|
+
);
|
|
206
|
+
registry.setTerminalFor(projectId, terminalA);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
210
|
+
// lockTerminalFor
|
|
211
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
212
|
+
|
|
213
|
+
function test_lockTerminalFor_snapshotsDefault() public {
|
|
214
|
+
// Set up default, no project-specific terminal.
|
|
215
|
+
vm.prank(owner);
|
|
216
|
+
registry.setDefaultTerminal(terminalA);
|
|
217
|
+
|
|
218
|
+
vm.mockCall(address(projects), abi.encodeCall(IERC721.ownerOf, (projectId)), abi.encode(projectOwner));
|
|
219
|
+
vm.mockCall(
|
|
220
|
+
address(permissions),
|
|
221
|
+
abi.encodeWithSignature(
|
|
222
|
+
"hasPermission(address,address,uint256,uint256,bool,bool)",
|
|
223
|
+
projectOwner,
|
|
224
|
+
projectOwner,
|
|
225
|
+
projectId,
|
|
226
|
+
JBPermissionIds.SET_ROUTER_TERMINAL,
|
|
227
|
+
true,
|
|
228
|
+
true
|
|
229
|
+
),
|
|
230
|
+
abi.encode(true)
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
vm.prank(projectOwner);
|
|
234
|
+
registry.lockTerminalFor(projectId);
|
|
235
|
+
|
|
236
|
+
assertTrue(registry.hasLockedTerminal(projectId));
|
|
237
|
+
// Should have snapshotted the default as the project's terminal.
|
|
238
|
+
assertEq(address(registry.terminalOf(projectId)), address(terminalA));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function test_lockTerminalFor_revertsIfNoTerminal() public {
|
|
242
|
+
vm.mockCall(address(projects), abi.encodeCall(IERC721.ownerOf, (projectId)), abi.encode(projectOwner));
|
|
243
|
+
vm.mockCall(
|
|
244
|
+
address(permissions),
|
|
245
|
+
abi.encodeWithSignature(
|
|
246
|
+
"hasPermission(address,address,uint256,uint256,bool,bool)",
|
|
247
|
+
projectOwner,
|
|
248
|
+
projectOwner,
|
|
249
|
+
projectId,
|
|
250
|
+
JBPermissionIds.SET_ROUTER_TERMINAL,
|
|
251
|
+
true,
|
|
252
|
+
true
|
|
253
|
+
),
|
|
254
|
+
abi.encode(true)
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
vm.prank(projectOwner);
|
|
258
|
+
vm.expectRevert(
|
|
259
|
+
abi.encodeWithSelector(
|
|
260
|
+
JBRouterTerminalRegistry.JBRouterTerminalRegistry_TerminalNotSet.selector, projectId
|
|
261
|
+
)
|
|
262
|
+
);
|
|
263
|
+
registry.lockTerminalFor(projectId);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
267
|
+
// supportsInterface
|
|
268
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
269
|
+
|
|
270
|
+
function test_supportsInterface() public view {
|
|
271
|
+
assertTrue(registry.supportsInterface(type(IJBRouterTerminalRegistry).interfaceId));
|
|
272
|
+
assertTrue(registry.supportsInterface(type(IJBTerminal).interfaceId));
|
|
273
|
+
assertTrue(registry.supportsInterface(type(IERC165).interfaceId));
|
|
274
|
+
assertFalse(registry.supportsInterface(bytes4(0xdeadbeef)));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
278
|
+
// pay (forwarding)
|
|
279
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
280
|
+
|
|
281
|
+
function test_pay_forwardsToDefault() public {
|
|
282
|
+
vm.prank(owner);
|
|
283
|
+
registry.setDefaultTerminal(terminalA);
|
|
284
|
+
|
|
285
|
+
// Mock the terminal's pay to return 100.
|
|
286
|
+
vm.mockCall(
|
|
287
|
+
address(terminalA),
|
|
288
|
+
abi.encodeWithSelector(IJBTerminal.pay.selector),
|
|
289
|
+
abi.encode(uint256(100))
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
// Send native tokens.
|
|
293
|
+
vm.deal(address(this), 1 ether);
|
|
294
|
+
uint256 returned = registry.pay{value: 1 ether}({
|
|
295
|
+
projectId: projectId,
|
|
296
|
+
token: JBConstants.NATIVE_TOKEN,
|
|
297
|
+
amount: 1 ether,
|
|
298
|
+
beneficiary: address(this),
|
|
299
|
+
minReturnedTokens: 0,
|
|
300
|
+
memo: "",
|
|
301
|
+
metadata: ""
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
assertEq(returned, 100);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
308
|
+
// addToBalanceOf (forwarding)
|
|
309
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
310
|
+
|
|
311
|
+
function test_addToBalanceOf_forwardsToDefault() public {
|
|
312
|
+
vm.prank(owner);
|
|
313
|
+
registry.setDefaultTerminal(terminalA);
|
|
314
|
+
|
|
315
|
+
// Mock the terminal's addToBalanceOf.
|
|
316
|
+
vm.mockCall(
|
|
317
|
+
address(terminalA),
|
|
318
|
+
abi.encodeWithSelector(IJBTerminal.addToBalanceOf.selector),
|
|
319
|
+
abi.encode()
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
// Send native tokens.
|
|
323
|
+
vm.deal(address(this), 1 ether);
|
|
324
|
+
registry.addToBalanceOf{value: 1 ether}({
|
|
325
|
+
projectId: projectId,
|
|
326
|
+
token: JBConstants.NATIVE_TOKEN,
|
|
327
|
+
amount: 1 ether,
|
|
328
|
+
shouldReturnHeldFees: false,
|
|
329
|
+
memo: "",
|
|
330
|
+
metadata: ""
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|