@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.
@@ -0,0 +1,466 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ import {JBPermissioned} from "@bananapus/core-v6/src/abstract/JBPermissioned.sol";
5
+ import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
6
+ import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
7
+ import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
8
+
9
+ import {JBMetadataResolver} from "@bananapus/core-v6/src/libraries/JBMetadataResolver.sol";
10
+ import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
11
+ import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
12
+ import {JBSingleAllowance} from "@bananapus/core-v6/src/structs/JBSingleAllowance.sol";
13
+ import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
14
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
15
+
16
+ import {Context} from "@openzeppelin/contracts/utils/Context.sol";
17
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
18
+ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
19
+ import {Address} from "@openzeppelin/contracts/utils/Address.sol";
20
+ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
21
+ import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
22
+ import {IPermit2} from "@uniswap/permit2/src/interfaces/IPermit2.sol";
23
+ import {IAllowanceTransfer} from "@uniswap/permit2/src/interfaces/IAllowanceTransfer.sol";
24
+
25
+ import {IJBRouterTerminalRegistry} from "./interfaces/IJBRouterTerminalRegistry.sol";
26
+
27
+ contract JBRouterTerminalRegistry is IJBRouterTerminalRegistry, JBPermissioned, Ownable, ERC2771Context {
28
+ // A library that adds default safety checks to ERC20 functionality.
29
+ using SafeERC20 for IERC20;
30
+
31
+ //*********************************************************************//
32
+ // --------------------------- custom errors ------------------------- //
33
+ //*********************************************************************//
34
+
35
+ error JBRouterTerminalRegistry_NoMsgValueAllowed(uint256 value);
36
+ error JBRouterTerminalRegistry_PermitAllowanceNotEnough(uint256 amount, uint256 allowanceAmount);
37
+ error JBRouterTerminalRegistry_TerminalLocked(uint256 projectId);
38
+ error JBRouterTerminalRegistry_TerminalNotAllowed(IJBTerminal terminal);
39
+ error JBRouterTerminalRegistry_TerminalNotSet(uint256 projectId);
40
+
41
+ //*********************************************************************//
42
+ // -------------------- public immutable properties ------------------ //
43
+ //*********************************************************************//
44
+
45
+ /// @notice The project registry.
46
+ IJBProjects public immutable override PROJECTS;
47
+
48
+ /// @notice The permit2 utility.
49
+ IPermit2 public immutable override PERMIT2;
50
+
51
+ //*********************************************************************//
52
+ // --------------------- public stored properties -------------------- //
53
+ //*********************************************************************//
54
+
55
+ /// @notice The default terminal to use.
56
+ IJBTerminal public override defaultTerminal;
57
+
58
+ /// @notice Whether the terminal for the given project is locked.
59
+ /// @custom:param projectId The ID of the project to get the locked terminal for.
60
+ mapping(uint256 projectId => bool) public override hasLockedTerminal;
61
+
62
+ /// @notice Whether the given terminal is allowed to be set for projects.
63
+ /// @custom:param terminal The terminal to check.
64
+ mapping(IJBTerminal terminal => bool) public override isTerminalAllowed;
65
+
66
+ //*********************************************************************//
67
+ // --------------------- internal stored properties ------------------ //
68
+ //*********************************************************************//
69
+
70
+ /// @notice The terminal explicitly set for the given project.
71
+ /// @custom:param projectId The ID of the project to get the terminal for.
72
+ mapping(uint256 projectId => IJBTerminal) internal _terminalOf;
73
+
74
+ //*********************************************************************//
75
+ // ---------------------------- constructor -------------------------- //
76
+ //*********************************************************************//
77
+
78
+ /// @param permissions The permissions contract.
79
+ /// @param projects The project registry.
80
+ /// @param permit2 The permit2 utility.
81
+ /// @param owner The owner of the contract.
82
+ /// @param trustedForwarder The trusted forwarder for the contract.
83
+ constructor(
84
+ IJBPermissions permissions,
85
+ IJBProjects projects,
86
+ IPermit2 permit2,
87
+ address owner,
88
+ address trustedForwarder
89
+ )
90
+ JBPermissioned(permissions)
91
+ ERC2771Context(trustedForwarder)
92
+ Ownable(owner)
93
+ {
94
+ PROJECTS = projects;
95
+ PERMIT2 = permit2;
96
+ }
97
+
98
+ //*********************************************************************//
99
+ // ------------------------- external views -------------------------- //
100
+ //*********************************************************************//
101
+
102
+ /// @notice The terminal for the given project, or the default terminal if none is set.
103
+ /// @param projectId The ID of the project to get the terminal for.
104
+ /// @return terminal The terminal for the project.
105
+ function terminalOf(uint256 projectId) external view override returns (IJBTerminal terminal) {
106
+ terminal = _terminalOf[projectId];
107
+ if (terminal == IJBTerminal(address(0))) terminal = defaultTerminal;
108
+ }
109
+
110
+ /// @notice Get the accounting context for the specified project ID and token.
111
+ /// @param projectId The ID of the project to get the accounting context for.
112
+ /// @param token The address of the token to get the accounting context for.
113
+ /// @return context A `JBAccountingContext` containing the accounting context for the project ID and token.
114
+ function accountingContextForTokenOf(
115
+ uint256 projectId,
116
+ address token
117
+ )
118
+ external
119
+ view
120
+ override
121
+ returns (JBAccountingContext memory context)
122
+ {
123
+ // Get the terminal for the project (falls back to default).
124
+ IJBTerminal terminal = _terminalOf[projectId];
125
+ if (terminal == IJBTerminal(address(0))) terminal = defaultTerminal;
126
+
127
+ // Get the accounting context for the token.
128
+ return terminal.accountingContextForTokenOf({projectId: projectId, token: token});
129
+ }
130
+
131
+ /// @notice Return all the accounting contexts for a specified project ID.
132
+ /// @param projectId The ID of the project to get the accounting contexts for.
133
+ /// @return contexts An array of `JBAccountingContext` containing the accounting contexts for the project ID.
134
+ function accountingContextsOf(uint256 projectId)
135
+ external
136
+ view
137
+ override
138
+ returns (JBAccountingContext[] memory contexts)
139
+ {
140
+ // Get the terminal for the project (falls back to default).
141
+ IJBTerminal terminal = _terminalOf[projectId];
142
+ if (terminal == IJBTerminal(address(0))) terminal = defaultTerminal;
143
+
144
+ // Get the accounting contexts.
145
+ return terminal.accountingContextsOf(projectId);
146
+ }
147
+
148
+ /// @notice Empty implementation to satisfy the interface. This terminal has no surplus.
149
+ function currentSurplusOf(
150
+ uint256 projectId,
151
+ JBAccountingContext[] memory accountingContexts,
152
+ uint256 decimals,
153
+ uint256 currency
154
+ )
155
+ external
156
+ view
157
+ override
158
+ returns (uint256)
159
+ {}
160
+
161
+ //*********************************************************************//
162
+ // -------------------------- public views --------------------------- //
163
+ //*********************************************************************//
164
+
165
+ function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
166
+ return interfaceId == type(IJBRouterTerminalRegistry).interfaceId
167
+ || interfaceId == type(IJBTerminal).interfaceId || interfaceId == type(IERC165).interfaceId;
168
+ }
169
+
170
+ //*********************************************************************//
171
+ // -------------------------- internal views ------------------------- //
172
+ //*********************************************************************//
173
+
174
+ /// @dev `ERC-2771` specifies the context as being a single address (20 bytes).
175
+ function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
176
+ return super._contextSuffixLength();
177
+ }
178
+
179
+ /// @notice The calldata. Preferred to use over `msg.data`.
180
+ /// @return calldata The `msg.data` of this call.
181
+ function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
182
+ return ERC2771Context._msgData();
183
+ }
184
+
185
+ /// @notice The message's sender. Preferred to use over `msg.sender`.
186
+ /// @return sender The address which sent this call.
187
+ function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
188
+ return ERC2771Context._msgSender();
189
+ }
190
+
191
+ //*********************************************************************//
192
+ // ---------------------- external transactions ---------------------- //
193
+ //*********************************************************************//
194
+
195
+ /// @notice Empty implementation to satisfy the interface.
196
+ function addAccountingContextsFor(
197
+ uint256 projectId,
198
+ JBAccountingContext[] calldata accountingContexts
199
+ )
200
+ external
201
+ override
202
+ {}
203
+
204
+ /// @notice Accepts funds for a given project and adds them to the project's balance in the resolved terminal.
205
+ /// @param projectId The ID of the project for which funds are being accepted.
206
+ /// @param token The address of the token being paid in.
207
+ /// @param amount The amount of tokens being paid in.
208
+ /// @param shouldReturnHeldFees A boolean to indicate whether held fees should be returned.
209
+ /// @param memo A memo to pass along to the emitted event.
210
+ /// @param metadata Bytes in `JBMetadataResolver`'s format.
211
+ function addToBalanceOf(
212
+ uint256 projectId,
213
+ address token,
214
+ uint256 amount,
215
+ bool shouldReturnHeldFees,
216
+ string calldata memo,
217
+ bytes calldata metadata
218
+ )
219
+ external
220
+ payable
221
+ override
222
+ {
223
+ // Get the terminal for the project (falls back to default).
224
+ IJBTerminal terminal = _terminalOf[projectId];
225
+ if (terminal == IJBTerminal(address(0))) terminal = defaultTerminal;
226
+
227
+ // Accept the funds for the token.
228
+ amount = _acceptFundsFor({token: token, amount: amount, metadata: metadata});
229
+
230
+ // Trigger any pre-transfer logic.
231
+ uint256 payValue = _beforeTransferFor({to: address(terminal), token: token, amount: amount});
232
+
233
+ // Forward to the resolved terminal.
234
+ terminal.addToBalanceOf{value: payValue}({
235
+ projectId: projectId,
236
+ token: token,
237
+ amount: amount,
238
+ shouldReturnHeldFees: shouldReturnHeldFees,
239
+ memo: memo,
240
+ metadata: metadata
241
+ });
242
+ }
243
+
244
+ /// @notice Allow a terminal.
245
+ /// @dev Only the owner can allow a terminal.
246
+ /// @param terminal The terminal to allow.
247
+ function allowTerminal(IJBTerminal terminal) external onlyOwner {
248
+ isTerminalAllowed[terminal] = true;
249
+
250
+ emit JBRouterTerminalRegistry_AllowTerminal(terminal);
251
+ }
252
+
253
+ /// @notice Disallow a terminal.
254
+ /// @dev Only the owner can disallow a terminal.
255
+ /// @param terminal The terminal to disallow.
256
+ function disallowTerminal(IJBTerminal terminal) external onlyOwner {
257
+ isTerminalAllowed[terminal] = false;
258
+
259
+ // Clear default terminal if it matches the terminal being disallowed.
260
+ if (defaultTerminal == terminal) defaultTerminal = IJBTerminal(address(0));
261
+
262
+ emit JBRouterTerminalRegistry_DisallowTerminal(terminal);
263
+ }
264
+
265
+ /// @notice Lock a terminal for a project.
266
+ /// @dev Only the project's owner or an address with the `JBPermissionIds.SET_ROUTER_TERMINAL` permission can lock.
267
+ /// @param projectId The ID of the project to lock the terminal for.
268
+ function lockTerminalFor(uint256 projectId) external {
269
+ // Enforce permissions.
270
+ _requirePermissionFrom({
271
+ account: PROJECTS.ownerOf(projectId),
272
+ projectId: projectId,
273
+ permissionId: JBPermissionIds.SET_ROUTER_TERMINAL
274
+ });
275
+
276
+ // Require a non-zero terminal before locking.
277
+ IJBTerminal terminal = _terminalOf[projectId];
278
+ if (terminal == IJBTerminal(address(0))) {
279
+ terminal = defaultTerminal;
280
+ if (terminal == IJBTerminal(address(0))) revert JBRouterTerminalRegistry_TerminalNotSet(projectId);
281
+ _terminalOf[projectId] = terminal;
282
+ }
283
+
284
+ hasLockedTerminal[projectId] = true;
285
+
286
+ emit JBRouterTerminalRegistry_LockTerminal(projectId);
287
+ }
288
+
289
+ /// @notice Empty implementation to satisfy the interface.
290
+ function migrateBalanceOf(
291
+ uint256 projectId,
292
+ address token,
293
+ IJBTerminal to
294
+ )
295
+ external
296
+ override
297
+ returns (uint256 balance)
298
+ {}
299
+
300
+ /// @notice Pay a project by forwarding the payment to the resolved terminal.
301
+ /// @param projectId The ID of the project being paid.
302
+ /// @param token The address of the token being paid in.
303
+ /// @param amount The amount of tokens being paid in.
304
+ /// @param beneficiary The beneficiary address to pass along.
305
+ /// @param minReturnedTokens The minimum number of project tokens expected in return.
306
+ /// @param memo A memo to pass along to the emitted event.
307
+ /// @param metadata Bytes in `JBMetadataResolver`'s format.
308
+ /// @return The number of tokens received.
309
+ function pay(
310
+ uint256 projectId,
311
+ address token,
312
+ uint256 amount,
313
+ address beneficiary,
314
+ uint256 minReturnedTokens,
315
+ string calldata memo,
316
+ bytes calldata metadata
317
+ )
318
+ external
319
+ payable
320
+ virtual
321
+ override
322
+ returns (uint256)
323
+ {
324
+ // Get the terminal for the project (falls back to default).
325
+ IJBTerminal terminal = _terminalOf[projectId];
326
+ if (terminal == IJBTerminal(address(0))) terminal = defaultTerminal;
327
+
328
+ // Accept the funds for the token.
329
+ amount = _acceptFundsFor({token: token, amount: amount, metadata: metadata});
330
+
331
+ // Trigger any pre-transfer logic.
332
+ uint256 payValue = _beforeTransferFor({to: address(terminal), token: token, amount: amount});
333
+
334
+ // Forward the payment to the terminal.
335
+ return terminal.pay{value: payValue}({
336
+ projectId: projectId,
337
+ token: token,
338
+ amount: amount,
339
+ beneficiary: beneficiary,
340
+ minReturnedTokens: minReturnedTokens,
341
+ memo: memo,
342
+ metadata: metadata
343
+ });
344
+ }
345
+
346
+ /// @notice Set the default terminal.
347
+ /// @dev Only the owner can set the default terminal.
348
+ /// @param terminal The terminal to set as the default.
349
+ function setDefaultTerminal(IJBTerminal terminal) external onlyOwner {
350
+ defaultTerminal = terminal;
351
+
352
+ // Allow the default terminal.
353
+ isTerminalAllowed[terminal] = true;
354
+
355
+ emit JBRouterTerminalRegistry_SetDefaultTerminal(terminal);
356
+ }
357
+
358
+ /// @notice Set the terminal for a project.
359
+ /// @dev Only the project's owner or an address with the `JBPermissionIds.SET_ROUTER_TERMINAL` permission can set.
360
+ /// @param projectId The ID of the project to set the terminal for.
361
+ /// @param terminal The terminal to set for the project.
362
+ function setTerminalFor(uint256 projectId, IJBTerminal terminal) external {
363
+ // Make sure the terminal is not locked.
364
+ if (hasLockedTerminal[projectId]) revert JBRouterTerminalRegistry_TerminalLocked(projectId);
365
+
366
+ if (!isTerminalAllowed[terminal]) revert JBRouterTerminalRegistry_TerminalNotAllowed(terminal);
367
+
368
+ // Enforce permissions.
369
+ _requirePermissionFrom({
370
+ account: PROJECTS.ownerOf(projectId),
371
+ projectId: projectId,
372
+ permissionId: JBPermissionIds.SET_ROUTER_TERMINAL
373
+ });
374
+
375
+ _terminalOf[projectId] = terminal;
376
+
377
+ emit JBRouterTerminalRegistry_SetTerminal(projectId, terminal);
378
+ }
379
+
380
+ //*********************************************************************//
381
+ // ---------------------- internal transactions ---------------------- //
382
+ //*********************************************************************//
383
+
384
+ /// @notice Accepts a token being paid in.
385
+ /// @param token The address of the token being paid in.
386
+ /// @param amount The amount of tokens being paid in.
387
+ /// @param metadata The metadata in which `permit2` context is provided.
388
+ /// @return amount The amount of tokens that have been accepted.
389
+ function _acceptFundsFor(address token, uint256 amount, bytes calldata metadata) internal returns (uint256) {
390
+ // If native tokens are being paid in, return the `msg.value`.
391
+ if (token == JBConstants.NATIVE_TOKEN) return msg.value;
392
+
393
+ // Otherwise, the `msg.value` should be 0.
394
+ if (msg.value != 0) revert JBRouterTerminalRegistry_NoMsgValueAllowed(msg.value);
395
+
396
+ // Unpack the `JBSingleAllowance` to use given by the frontend.
397
+ (bool exists, bytes memory parsedMetadata) =
398
+ JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("permit2"), metadata: metadata});
399
+
400
+ // If the metadata contained permit data, use it to set the allowance.
401
+ if (exists) {
402
+ // Keep a reference to the allowance context parsed from the metadata.
403
+ (JBSingleAllowance memory allowance) = abi.decode(parsedMetadata, (JBSingleAllowance));
404
+
405
+ // Make sure the permit allowance is enough for this payment.
406
+ if (amount > allowance.amount) {
407
+ revert JBRouterTerminalRegistry_PermitAllowanceNotEnough(amount, allowance.amount);
408
+ }
409
+
410
+ // Keep a reference to the permit rules.
411
+ IAllowanceTransfer.PermitSingle memory permitSingle = IAllowanceTransfer.PermitSingle({
412
+ details: IAllowanceTransfer.PermitDetails({
413
+ token: token, amount: allowance.amount, expiration: allowance.expiration, nonce: allowance.nonce
414
+ }),
415
+ spender: address(this),
416
+ sigDeadline: allowance.sigDeadline
417
+ });
418
+
419
+ try PERMIT2.permit({owner: _msgSender(), permitSingle: permitSingle, signature: allowance.signature}) {}
420
+ catch {}
421
+ }
422
+
423
+ // Transfer the tokens from the `_msgSender()` to this terminal.
424
+ _transferFrom({from: _msgSender(), to: payable(address(this)), token: token, amount: amount});
425
+
426
+ return amount;
427
+ }
428
+
429
+ /// @notice Logic to be triggered before transferring tokens from this terminal.
430
+ /// @param to The address to transfer tokens to.
431
+ /// @param token The token being transferred.
432
+ /// @param amount The amount of tokens to transfer.
433
+ /// @return payValue The amount that'll be paid as a `msg.value`.
434
+ function _beforeTransferFor(address to, address token, uint256 amount) internal virtual returns (uint256) {
435
+ // If the token is the native token, return early.
436
+ if (token == JBConstants.NATIVE_TOKEN) return amount;
437
+
438
+ // Otherwise, set the appropriate allowance for the recipient.
439
+ IERC20(token).safeIncreaseAllowance(to, amount);
440
+
441
+ return 0;
442
+ }
443
+
444
+ /// @notice Transfers tokens.
445
+ /// @param from The address to transfer tokens from.
446
+ /// @param to The address to transfer tokens to.
447
+ /// @param token The address of the token being transferred.
448
+ /// @param amount The amount of tokens to transfer.
449
+ function _transferFrom(address from, address payable to, address token, uint256 amount) internal virtual {
450
+ if (from == address(this)) {
451
+ // If the token is native token, assume the `sendValue` standard.
452
+ if (token == JBConstants.NATIVE_TOKEN) return Address.sendValue(to, amount);
453
+
454
+ // If the transfer is from this terminal, use `safeTransfer`.
455
+ return IERC20(token).safeTransfer(to, amount);
456
+ }
457
+
458
+ // If there's sufficient approval, transfer normally.
459
+ if (IERC20(token).allowance({owner: address(from), spender: address(this)}) >= amount) {
460
+ return IERC20(token).safeTransferFrom(from, to, amount);
461
+ }
462
+
463
+ // Otherwise, attempt to use the `permit2` method.
464
+ PERMIT2.transferFrom(from, to, uint160(amount), token);
465
+ }
466
+ }
@@ -0,0 +1,45 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {IUniswapV3Pool} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
5
+ import {PoolInfo} from "../structs/PoolInfo.sol";
6
+
7
+ /// @notice A terminal that routes payments by discovering what token a project accepts and converting automatically.
8
+ interface IJBRouterTerminal {
9
+ error JBRouterTerminal_NoRouteFound(uint256 projectId, address tokenIn);
10
+ error JBRouterTerminal_TokenNotAccepted(uint256 projectId, address token);
11
+ error JBRouterTerminal_CallerNotPool(address caller);
12
+ error JBRouterTerminal_CallerNotPoolManager(address caller);
13
+ error JBRouterTerminal_SlippageExceeded(uint256 amountOut, uint256 minAmountOut);
14
+ error JBRouterTerminal_NoPoolFound(address tokenIn, address tokenOut);
15
+ error JBRouterTerminal_NoCashOutPath(uint256 sourceProjectId, uint256 destProjectId);
16
+ error JBRouterTerminal_NoMsgValueAllowed(uint256 value);
17
+ error JBRouterTerminal_PermitAllowanceNotEnough(uint256 amount, uint256 allowance);
18
+ error JBRouterTerminal_NoLiquidity();
19
+ error JBRouterTerminal_NoObservationHistory();
20
+ error JBRouterTerminal_AmountOverflow(uint256 amount);
21
+
22
+ /// @notice Search the Uniswap V3 factory for a pool between two tokens across common fee tiers.
23
+ /// @param normalizedTokenIn The input token (wrapped if native).
24
+ /// @param normalizedTokenOut The output token (wrapped if native).
25
+ /// @return pool The pool with the highest liquidity.
26
+ function discoverPool(
27
+ address normalizedTokenIn,
28
+ address normalizedTokenOut
29
+ )
30
+ external
31
+ view
32
+ returns (IUniswapV3Pool pool);
33
+
34
+ /// @notice Discover the best pool across both V3 and V4 for a token pair.
35
+ /// @param normalizedTokenIn The input token (wrapped if native).
36
+ /// @param normalizedTokenOut The output token (wrapped if native).
37
+ /// @return pool The best pool found.
38
+ function discoverBestPool(
39
+ address normalizedTokenIn,
40
+ address normalizedTokenOut
41
+ )
42
+ external
43
+ view
44
+ returns (PoolInfo memory pool);
45
+ }
@@ -0,0 +1,62 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
5
+ import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
6
+ import {IPermit2} from "@uniswap/permit2/src/interfaces/IPermit2.sol";
7
+
8
+ interface IJBRouterTerminalRegistry is IJBTerminal {
9
+ event JBRouterTerminalRegistry_AllowTerminal(IJBTerminal terminal);
10
+ event JBRouterTerminalRegistry_DisallowTerminal(IJBTerminal terminal);
11
+ event JBRouterTerminalRegistry_LockTerminal(uint256 projectId);
12
+ event JBRouterTerminalRegistry_SetDefaultTerminal(IJBTerminal terminal);
13
+ event JBRouterTerminalRegistry_SetTerminal(uint256 indexed projectId, IJBTerminal terminal);
14
+
15
+ /// @notice The project registry.
16
+ /// @return The projects contract.
17
+ function PROJECTS() external view returns (IJBProjects);
18
+
19
+ /// @notice The permit2 utility used for token approvals.
20
+ /// @return The permit2 contract.
21
+ function PERMIT2() external view returns (IPermit2);
22
+
23
+ /// @notice The default terminal used when a project has not set a specific terminal.
24
+ /// @return The default terminal.
25
+ function defaultTerminal() external view returns (IJBTerminal);
26
+
27
+ /// @notice Whether the terminal for the given project is locked and cannot be changed.
28
+ /// @param projectId The ID of the project.
29
+ /// @return Whether the terminal is locked.
30
+ function hasLockedTerminal(uint256 projectId) external view returns (bool);
31
+
32
+ /// @notice The terminal for the given project, or the default terminal if none is set.
33
+ /// @param projectId The ID of the project.
34
+ /// @return The terminal for the project.
35
+ function terminalOf(uint256 projectId) external view returns (IJBTerminal);
36
+
37
+ /// @notice Whether the given terminal is allowed to be set for projects.
38
+ /// @param terminal The terminal to check.
39
+ /// @return Whether the terminal is allowed.
40
+ function isTerminalAllowed(IJBTerminal terminal) external view returns (bool);
41
+
42
+ /// @notice Allow a terminal to be used by projects.
43
+ /// @param terminal The terminal to allow.
44
+ function allowTerminal(IJBTerminal terminal) external;
45
+
46
+ /// @notice Disallow a terminal from being used by projects.
47
+ /// @param terminal The terminal to disallow.
48
+ function disallowTerminal(IJBTerminal terminal) external;
49
+
50
+ /// @notice Lock the terminal for a project, preventing it from being changed.
51
+ /// @param projectId The ID of the project to lock the terminal for.
52
+ function lockTerminalFor(uint256 projectId) external;
53
+
54
+ /// @notice Set the default terminal used when a project has not set a specific terminal.
55
+ /// @param terminal The terminal to set as the default.
56
+ function setDefaultTerminal(IJBTerminal terminal) external;
57
+
58
+ /// @notice Set the terminal for a specific project.
59
+ /// @param projectId The ID of the project to set the terminal for.
60
+ /// @param terminal The terminal to set.
61
+ function setTerminalFor(uint256 projectId, IJBTerminal terminal) external;
62
+ }
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: GPL-2.0-or-later
2
+ pragma solidity ^0.8.0;
3
+
4
+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5
+
6
+ /// @title Interface for WETH9
7
+ interface IWETH9 is IERC20 {
8
+ /// @notice Deposit ether to get wrapped ether
9
+ function deposit() external payable;
10
+
11
+ /// @notice Withdraw wrapped ether to get ether
12
+ function withdraw(uint256) external;
13
+ }