@bananapus/suckers-v6 0.0.34 → 0.0.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/suckers-v6",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -151,7 +151,7 @@ contract JBArbitrumSucker is JBSucker, IJBArbitrumSucker {
151
151
  /// @notice Uses the L1/L2 gateway to send the root and assets over the bridge to the peer.
152
152
  /// @param transportPayment the amount of `msg.value` that is going to get paid for sending this message.
153
153
  /// @param token The token to bridge the outbox tree for.
154
- /// @param remoteToken Information about the remote token being bridged to.
154
+ /// @param remoteToken Information about the remote token to bridge to.
155
155
  // forge-lint: disable-next-line(mixed-case-function)
156
156
  function _sendRootOverAMB(
157
157
  uint256 transportPayment,
@@ -174,7 +174,7 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
174
174
  // Decode the root message from the payload.
175
175
  JBMessageRoot memory root = abi.decode(payload, (JBMessageRoot));
176
176
 
177
- // Only unwrap WETH -> ETH when the root targets native token (not when claiming WETH as ERC-20).
177
+ // Only unwrap wrapped native token when the root targets native token (not when claiming it as ERC-20).
178
178
  if (root.token == bytes32(uint256(uint160(JBConstants.NATIVE_TOKEN)))) {
179
179
  JBCCIPLib.unwrapReceivedTokens({
180
180
  ccipRouter: CCIP_ROUTER, destTokenAmounts: any2EvmMessage.destTokenAmounts
@@ -201,7 +201,7 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
201
201
  /// @param transportPayment The amount of `msg.value` that is going to get paid for sending this message.
202
202
  /// @param token The token to bridge the outbox tree for.
203
203
  /// @param amount The amount of tokens to bridge.
204
- /// @param remoteToken Information about the remote token being bridged to.
204
+ /// @param remoteToken Information about the remote token to bridge to.
205
205
  /// @param sucker_message The message root to send to the remote peer.
206
206
  // forge-lint: disable-next-line(mixed-case-function)
207
207
  function _sendRootOverAMB(
@@ -224,7 +224,7 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
224
224
  // Add extra gas for the ERC-20 token transfer on the remote chain.
225
225
  gasLimit += remoteToken.minGas;
226
226
 
227
- // Wrap native ETH -> WETH if needed, build the CCIP token amounts array, and approve the router.
227
+ // Wrap native tokens if needed, build the CCIP token amounts array, and approve the router.
228
228
  // slither-disable-next-line unused-return
229
229
  (tokenAmounts,) = JBCCIPLib.prepareTokenAmounts({ccipRouter: CCIP_ROUTER, token: token, amount: amount});
230
230
  } else {
@@ -281,15 +281,15 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
281
281
  ///
282
282
  /// Example: ETH mainnet (native = ETH) <-> Celo (native = CELO, ETH is an ERC-20).
283
283
  /// - On mainnet: `mapToken({localToken: NATIVE_TOKEN, remoteToken: celoETH_address})`
284
- /// - Sending: `_sendRootOverAMB` wraps native ETH -> WETH, bridges WETH via CCIP.
285
- /// - Receiving: `ccipReceive` checks `root.token == NATIVE_TOKEN` to decide whether to unwrap WETH -> ETH.
284
+ /// - Sending: `_sendRootOverAMB` wraps native tokens, bridges them via CCIP.
285
+ /// - Receiving: `ccipReceive` checks `root.token == NATIVE_TOKEN` to decide whether to unwrap.
286
286
  /// If `root.token` is an ERC-20 address (like celoETH), no unwrap occurs — tokens stay as ERC-20.
287
287
  ///
288
288
  /// The base class restriction (`NATIVE_TOKEN` can only map to `NATIVE_TOKEN` or `address(0)`) is intentionally
289
289
  /// removed here. The base class retains that restriction for OP/Arbitrum where both chains share ETH as native.
290
290
  function _validateTokenMapping(JBTokenMapping calldata map) internal pure virtual override {
291
291
  // Enforce a reasonable minimum gas limit for bridging. A minimum which is too low could lead to the loss of
292
- // funds. CCIP wraps native tokens to WETH before bridging (see `_sendRootOverAMB`), so ALL tokens —
292
+ // funds. CCIP wraps native tokens before bridging (see `_sendRootOverAMB`), so ALL tokens —
293
293
  // including native — need sufficient gas for an ERC-20 transfer on the remote chain.
294
294
  if (map.minGas < MESSENGER_ERC20_MIN_GAS_LIMIT) {
295
295
  revert JBSucker_BelowMinGas({minGas: map.minGas, minGasLimit: MESSENGER_ERC20_MIN_GAS_LIMIT});
@@ -20,7 +20,7 @@ import {JBRemoteToken} from "./structs/JBRemoteToken.sol";
20
20
  import {JBTokenMapping} from "./structs/JBTokenMapping.sol";
21
21
 
22
22
  /// @notice A `JBSucker` implementation for Celo — an OP Stack chain with a custom gas token (CELO, not ETH).
23
- /// @dev ETH exists on Celo only as an ERC-20 (WETH). This sucker wraps native ETH → WETH before bridging
23
+ /// @dev ETH exists on Celo only as an ERC-20. This sucker wraps native ETH before bridging
24
24
  /// as ERC-20 via the OP standard bridge, and removes the `NATIVE_TOKEN → NATIVE_TOKEN` restriction so that
25
25
  /// native ETH can map to a remote ERC-20.
26
26
  contract JBCeloSucker is JBOptimismSucker {
@@ -28,8 +28,8 @@ contract JBCeloSucker is JBOptimismSucker {
28
28
  // --------------- public immutable stored properties ---------------- //
29
29
  //*********************************************************************//
30
30
 
31
- /// @notice The wrapped native token (WETH) on the local chain.
32
- IWrappedNativeToken public immutable WRAPPED_NATIVE;
31
+ /// @notice The ERC-20 wrapper for the chain's native token on the local chain.
32
+ IWrappedNativeToken public immutable WRAPPED_NATIVE_TOKEN;
33
33
 
34
34
  //*********************************************************************//
35
35
  // ---------------------------- constructor -------------------------- //
@@ -53,7 +53,7 @@ contract JBCeloSucker is JBOptimismSucker {
53
53
  JBOptimismSucker(deployer, directory, permissions, prices, tokens, feeProjectId, registry, trustedForwarder)
54
54
  {
55
55
  // Fetch the wrapped native token by doing a callback to the deployer contract.
56
- WRAPPED_NATIVE = JBCeloSuckerDeployer(deployer).wrappedNative();
56
+ WRAPPED_NATIVE_TOKEN = JBCeloSuckerDeployer(deployer).wrappedNative();
57
57
  }
58
58
 
59
59
  //*********************************************************************//
@@ -73,24 +73,25 @@ contract JBCeloSucker is JBOptimismSucker {
73
73
  // --------------------- internal transactions ----------------------- //
74
74
  //*********************************************************************//
75
75
 
76
- /// @notice Unwraps WETH native ETH before adding to the project's balance.
77
- /// @dev When tokens are bridged from Celo → L1 via the OP bridge, L1 WETH (ERC-20) is released to the sucker.
78
- /// But the L1 project's terminal accepts native ETH (NATIVE_TOKEN), not WETH. This override unwraps the WETH
76
+ /// @notice Unwraps wrapped native tokens before adding to the project's balance.
77
+ /// @dev When tokens are bridged from Celo → L1 via the OP bridge, wrapped native tokens (ERC-20) are released to
78
+ /// the sucker. But the L1 project's terminal accepts native ETH (NATIVE_TOKEN), not the wrapped form. This override
79
+ /// unwraps
79
80
  /// and adds native ETH to the project's balance.
80
81
  /// @param token The terminal token to add to the project's balance.
81
82
  /// @param amount The amount of terminal tokens to add to the project's balance.
82
83
  /// @param cachedProjectId The cached project ID to avoid redundant storage reads.
83
84
  function _addToBalance(address token, uint256 amount, uint256 cachedProjectId) internal override {
84
- if (token == address(WRAPPED_NATIVE)) {
85
- // Check addable amount against WETH balance before unwrapping.
85
+ if (token == address(WRAPPED_NATIVE_TOKEN)) {
86
+ // Check addable amount against wrapped native token balance before unwrapping.
86
87
  uint256 addableAmount = amountToAddToBalanceOf(token);
87
88
  if (amount > addableAmount) {
88
89
  revert JBSucker_InsufficientBalance({amount: amount, balance: addableAmount});
89
90
  }
90
91
 
91
- // Unwrap WETH → native ETH.
92
+ // Unwrap wrapped native tokens → native tokens.
92
93
  // slither-disable-next-line calls-loop
93
- WRAPPED_NATIVE.withdraw(amount);
94
+ WRAPPED_NATIVE_TOKEN.withdraw(amount);
94
95
 
95
96
  // Get the project's primary terminal for native token.
96
97
  // slither-disable-next-line calls-loop
@@ -118,11 +119,11 @@ contract JBCeloSucker is JBOptimismSucker {
118
119
 
119
120
  /// @notice Use the `OPMESSENGER` to send the outbox tree for the `token` and the corresponding funds to the peer
120
121
  /// over the `OPBRIDGE`.
121
- /// @dev For Celo, native ETH is wrapped to WETH and bridged as ERC-20. The messenger message is sent with
122
+ /// @dev For Celo, native ETH is wrapped and bridged as ERC-20. The messenger message is sent with
122
123
  /// `nativeValue = 0` because Celo's native token is CELO (not ETH), so we never attach ETH as msg.value.
123
124
  /// @param transportPayment the amount of `msg.value` that is going to get paid for sending this message.
124
125
  /// @param token The token to bridge the outbox tree for.
125
- /// @param remoteToken Information about the remote token being bridged to.
126
+ /// @param remoteToken Information about the remote token to bridge to.
126
127
  // forge-lint: disable-next-line(mixed-case-function)
127
128
  function _sendRootOverAMB(
128
129
  uint256 transportPayment,
@@ -146,13 +147,13 @@ contract JBCeloSucker is JBOptimismSucker {
146
147
  address peerAddress = _toAddress(peer());
147
148
 
148
149
  if (amount != 0) {
149
- // Determine the local token to bridge — native ETH is wrapped to WETH first.
150
+ // Determine the local token to bridge — native ETH is wrapped first.
150
151
  address bridgeToken = token;
151
152
  if (token == JBConstants.NATIVE_TOKEN) {
152
- // Wrap native ETH → WETH so it can be bridged as ERC-20.
153
+ // Wrap native tokens so they can be bridged as ERC-20.
153
154
  // slither-disable-next-line arbitrary-send-eth,calls-loop
154
- WRAPPED_NATIVE.deposit{value: amount}();
155
- bridgeToken = address(WRAPPED_NATIVE);
155
+ WRAPPED_NATIVE_TOKEN.deposit{value: amount}();
156
+ bridgeToken = address(WRAPPED_NATIVE_TOKEN);
156
157
  }
157
158
 
158
159
  // Approve the bridge to spend the token.
@@ -183,11 +184,11 @@ contract JBCeloSucker is JBOptimismSucker {
183
184
  }
184
185
 
185
186
  /// @notice Allow `NATIVE_TOKEN` to map to any remote token (not just `NATIVE_TOKEN`).
186
- /// @dev Celo uses CELO as native gas token. ETH is an ERC-20 on Celo (WETH). So `NATIVE_TOKEN` on L1
187
+ /// @dev Celo uses CELO as native gas token. ETH is an ERC-20 on Celo. So `NATIVE_TOKEN` on L1
187
188
  /// maps to an ERC-20 address on Celo, not to `NATIVE_TOKEN`. The base class restriction is removed.
188
189
  function _validateTokenMapping(JBTokenMapping calldata map) internal pure virtual override {
189
190
  // Enforce a reasonable minimum gas limit for bridging. Since we always bridge as ERC-20
190
- // (wrapping native ETH to WETH), all tokens need sufficient gas for an ERC-20 transfer.
191
+ // (wrapping native tokens), all tokens need sufficient gas for an ERC-20 transfer.
191
192
  if (map.minGas < MESSENGER_ERC20_MIN_GAS_LIMIT) {
192
193
  revert JBSucker_BelowMinGas({minGas: map.minGas, minGasLimit: MESSENGER_ERC20_MIN_GAS_LIMIT});
193
194
  }
@@ -87,7 +87,7 @@ contract JBOptimismSucker is JBSucker, IJBOptimismSucker {
87
87
  /// over the `OPBRIDGE`.
88
88
  /// @param transportPayment the amount of `msg.value` that is going to get paid for sending this message.
89
89
  /// @param token The token to bridge the outbox tree for.
90
- /// @param remoteToken Information about the remote token being bridged to.
90
+ /// @param remoteToken Information about the remote token to bridge to.
91
91
  // forge-lint: disable-next-line(mixed-case-function)
92
92
  function _sendRootOverAMB(
93
93
  uint256 transportPayment,
package/src/JBSucker.sol CHANGED
@@ -255,8 +255,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
255
255
  /// @notice Accepts incoming native token (ETH) transfers.
256
256
  /// @dev This receive function is intentionally unrestricted. It must accept ETH from multiple sources:
257
257
  /// - Bridge contracts (e.g., Optimism's StandardBridge, Arbitrum's gateway) delivering bridged native tokens.
258
- /// - WETH contracts during unwrapping (e.g., CCIP sucker unwraps WETH via `withdraw()` which sends ETH here).
259
- /// - Terminals returning native tokens during `cashOutTokensOf` (backing asset pulls).
258
+ /// - Wrapped native token contracts during unwrapping (e.g., CCIP sucker unwraps via `withdraw()` which sends
259
+ /// native tokens here). - Terminals returning native tokens during `cashOutTokensOf` (backing asset pulls).
260
260
  /// @dev Restricting this to known senders would risk breaking bridge integrations, as bridge contracts may change
261
261
  /// addresses or use proxy patterns. The sucker's accounting (`_outboxOf[token].balance` and
262
262
  /// `amountToAddToBalanceOf`) already tracks expected native token amounts, so excess ETH sent here does not
@@ -389,7 +389,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
389
389
  /// messages time to arrive, accepting roots after deprecation provides a stronger guarantee that users can always
390
390
  /// claim their bridged tokens. Double-spend is not a concern because `toRemote` is already disabled in
391
391
  /// `SENDING_DISABLED` and `DEPRECATED` states, so no new outbound transfers can occur.
392
- /// @param root The merkle root, token, and amount being received.
392
+ /// @param root The merkle root, token, and amount to receive.
393
393
  function fromRemote(JBMessageRoot calldata root) external payable {
394
394
  // Make sure that the message came from our peer.
395
395
  // Use msg.sender (not _msgSender()) because bridge messengers never use ERC2771 meta-transactions.
@@ -620,7 +620,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
620
620
  /// for the original caller instead of being added back to `transportPayment`. This preserves
621
621
  /// `transportPayment = msg.value - fee`, which is critical for zero-cost bridges (OP, Base, Celo, Arb L2->L1)
622
622
  /// that revert on non-zero transport payment. The retained fee is excluded from `amountToAddToBalanceOf`.
623
- /// @param token The terminal token being bridged.
623
+ /// @param token The terminal token to bridge.
624
624
  function toRemote(address token) external payable override {
625
625
  JBRemoteToken memory remoteToken = _remoteTokenFor[token];
626
626
 
@@ -963,7 +963,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
963
963
  }
964
964
 
965
965
  /// @notice The action(s) to perform after a user has succesfully proven their claim.
966
- /// @param terminalToken The terminal token being sucked.
966
+ /// @param terminalToken The terminal token to suck.
967
967
  /// @param terminalTokenAmount The amount of terminal tokens.
968
968
  /// @param projectTokenAmount The amount of project tokens.
969
969
  /// @param beneficiary The beneficiary of the project tokens (bytes32 for cross-VM compatibility).
@@ -1000,8 +1000,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1000
1000
  }
1001
1001
 
1002
1002
  /// @notice Inserts a new leaf into the outbox merkle tree for the specified `token`.
1003
- /// @param projectTokenCount The amount of project tokens being cashed out.
1004
- /// @param token The terminal token being cashed out for.
1003
+ /// @param projectTokenCount The amount of project tokens to cash out.
1004
+ /// @param token The terminal token to cash out for.
1005
1005
  /// @param terminalTokenAmount The amount of terminal tokens reclaimed by cashing out.
1006
1006
  /// @param beneficiary The beneficiary of the project tokens on the remote chain (bytes32 for cross-VM
1007
1007
  /// compatibility).
@@ -1127,7 +1127,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1127
1127
  }
1128
1128
 
1129
1129
  /// @notice Cash out project tokens for terminal tokens.
1130
- /// @param projectToken The project token being cashed out (unused, kept for interface compatibility).
1130
+ /// @param projectToken The project token to cash out (unused, kept for interface compatibility).
1131
1131
  /// @param count The number of project tokens to cash out.
1132
1132
  /// @param token The terminal token to cash out for.
1133
1133
  /// @param minTokensReclaimed The minimum amount of terminal tokens to reclaim. If the amount reclaimed is less than
@@ -1245,8 +1245,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1245
1245
  /// @dev This is chain/sucker/bridge specific logic.
1246
1246
  /// @param transportPayment The amount of `msg.value` that is going to get paid for sending this message.
1247
1247
  /// @param index The index of the most recent message that is part of the root.
1248
- /// @param token The terminal token being bridged.
1249
- /// @param amount The amount of terminal tokens being bridged.
1248
+ /// @param token The terminal token to bridge.
1249
+ /// @param amount The amount of terminal tokens to bridge.
1250
1250
  /// @param remoteToken The remote token which the terminal token is mapped to.
1251
1251
  /// @param message The message/root to send to the remote chain.
1252
1252
  // forge-lint: disable-next-line(mixed-case-function)
@@ -1268,7 +1268,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1268
1268
  /// @param terminalToken The terminal token that the project tokens were cashed out for.
1269
1269
  /// @param terminalTokenAmount The amount of terminal tokens reclaimed by the cash out.
1270
1270
  /// @param beneficiary The beneficiary of the project tokens (bytes32 for cross-VM compatibility).
1271
- /// @param index The index of the leaf being proved in the terminal token's inbox tree.
1271
+ /// @param index The index of the leaf to prove in the terminal token's inbox tree.
1272
1272
  /// @param leaves The leaves that prove that the leaf at the `index` is in the tree (i.e. the merkle branch that the
1273
1273
  /// leaf is on).
1274
1274
  function _validate(
@@ -1364,7 +1364,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1364
1364
  /// @param terminalToken The terminal token that the project tokens were cashed out for.
1365
1365
  /// @param terminalTokenAmount The amount of terminal tokens reclaimed by the cash out.
1366
1366
  /// @param beneficiary The beneficiary of the project tokens (bytes32 for cross-VM compatibility).
1367
- /// @param index The index of the leaf being proved in the terminal token's inbox tree.
1367
+ /// @param index The index of the leaf to prove in the terminal token's inbox tree.
1368
1368
  /// @param leaves The leaves that prove that the leaf at the `index` is in the tree (i.e. the merkle branch that the
1369
1369
  /// leaf is on).
1370
1370
  function _validateForEmergencyExit(
@@ -1467,8 +1467,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1467
1467
  }
1468
1468
 
1469
1469
  /// @notice Builds a hash as they are stored in the merkle tree.
1470
- /// @param projectTokenCount The number of project tokens being cashed out.
1471
- /// @param terminalTokenAmount The amount of terminal tokens being reclaimed by the cash out.
1470
+ /// @param projectTokenCount The number of project tokens to cash out.
1471
+ /// @param terminalTokenAmount The amount of terminal tokens to reclaim from the cash out.
1472
1472
  /// @param beneficiary The beneficiary which will receive the project tokens (bytes32 for cross-VM compatibility).
1473
1473
  /// @return hash The keccak256 hash of the leaf data.
1474
1474
  function _buildTreeHash(
@@ -1605,9 +1605,9 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1605
1605
  /// @dev Delegates snapshot construction to JBSuckerLib (deployed library, called via DELEGATECALL) to reduce
1606
1606
  /// child contract bytecode.
1607
1607
  /// @param transportPayment The amount of `msg.value` that is going to get paid for sending this message.
1608
- /// @param token The terminal token being bridged.
1608
+ /// @param token The terminal token to bridge.
1609
1609
  /// @param remoteToken The remote token which the terminal token is mapped to.
1610
- /// @param amount The amount of terminal tokens being bridged.
1610
+ /// @param amount The amount of terminal tokens to bridge.
1611
1611
  /// @param nonce The outbox nonce for this send.
1612
1612
  /// @param root The merkle root of the outbox tree.
1613
1613
  /// @param index The index of the most recent message that is part of the root.
@@ -20,9 +20,9 @@ import {JBSuckerDeployerConfig} from "./structs/JBSuckerDeployerConfig.sol";
20
20
  import {JBSuckersPair} from "./structs/JBSuckersPair.sol";
21
21
 
22
22
  /// @notice The canonical registry that deploys, tracks, and governs cross-chain suckers for Juicebox projects. It
23
- /// maintains an allowlist of approved deployer contracts, enforces one active sucker per peer chain per project,
24
- /// manages the global `toRemoteFee` (paid into the protocol fee project on each bridge send), and provides aggregate
25
- /// views of remote-chain balances, surplus, and token supply across all of a project's suckers.
23
+ /// maintains an allowlist of approved deployer contracts, allows multiple active suckers per peer chain for bridge
24
+ /// resilience, manages the global `toRemoteFee` (paid into the protocol fee project on each bridge send), and provides
25
+ /// aggregate views of remote-chain balances, surplus, and token supply across all of a project's suckers.
26
26
  contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerRegistry {
27
27
  using EnumerableMap for EnumerableMap.AddressToUintMap;
28
28
 
@@ -30,7 +30,6 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
30
30
  // --------------------------- custom errors ------------------------- //
31
31
  //*********************************************************************//
32
32
 
33
- error JBSuckerRegistry_DuplicatePeerChain(uint256 projectId, uint256 peerChainId);
34
33
  error JBSuckerRegistry_FeeExceedsMax(uint256 fee, uint256 max);
35
34
  error JBSuckerRegistry_InvalidDeployer(IJBSuckerDeployer deployer);
36
35
  error JBSuckerRegistry_SuckerDoesNotBelongToProject(uint256 projectId, address sucker);
@@ -401,8 +400,8 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
401
400
  /// @param values The aggregate values recorded so far.
402
401
  /// @param hasActiveValue Whether the recorded value for each index came from an active sucker.
403
402
  /// @param chainCount The number of populated chain entries.
404
- /// @param chainId The peer-chain id being recorded.
405
- /// @param value The value being recorded.
403
+ /// @param chainId The peer-chain id to record.
404
+ /// @param value The value to record.
406
405
  /// @param isActive Whether the value came from an active sucker.
407
406
  /// @return The updated number of populated chain entries.
408
407
  function _recordPeerValue(
@@ -420,8 +419,9 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
420
419
  {
421
420
  for (uint256 j; j < chainCount;) {
422
421
  if (chainIds[j] == chainId) {
423
- // An active sucker is the live source for this chain. If several active suckers briefly exist during
424
- // migration, keep the max value so a lower stale snapshot cannot undercount the project.
422
+ // Each sucker caches the entire remote chain's state (not a per-sucker share), so multiple
423
+ // suckers targeting the same chain report redundant snapshots. MAX picks the freshest value
424
+ // without double-counting — SUM would inflate bonding curve denominators.
425
425
  if (isActive) {
426
426
  if (!hasActiveValue[j] || value > values[j]) values[j] = value;
427
427
  hasActiveValue[j] = true;
@@ -444,30 +444,6 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
444
444
  }
445
445
  }
446
446
 
447
- /// @notice Reverts if any active sucker for the given project already targets the same peer chain as the new
448
- /// sucker.
449
- /// @param projectId The ID of the project to check.
450
- /// @param newSucker The newly created sucker to validate.
451
- function _revertIfDuplicatePeerChain(uint256 projectId, IJBSucker newSucker) internal view {
452
- // The new sucker is registry-deployed and trusted for this validation.
453
- // slither-disable-next-line calls-loop
454
- uint256 newPeerChainId = newSucker.peerChainId();
455
- address[] memory existing = _suckersOf[projectId].keys();
456
- for (uint256 i; i < existing.length;) {
457
- // slither-disable-next-line unused-return
458
- (, uint256 val) = _suckersOf[projectId].tryGet(existing[i]);
459
- if (val == _SUCKER_EXISTS) {
460
- // slither-disable-next-line calls-loop
461
- if (IJBSucker(existing[i]).peerChainId() == newPeerChainId) {
462
- revert JBSuckerRegistry_DuplicatePeerChain(projectId, newPeerChainId);
463
- }
464
- }
465
- unchecked {
466
- ++i;
467
- }
468
- }
469
- }
470
-
471
447
  //*********************************************************************//
472
448
  // ---------------------- public transactions ----------------------- //
473
449
  //*********************************************************************//
@@ -502,9 +478,9 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
502
478
  }
503
479
 
504
480
  /// @notice Deploy one or more cross-chain suckers for a project in a single transaction. Each sucker is created via
505
- /// its deployer, registered in this registry, checked for duplicate peer chains, and immediately configured with
506
- /// its token mappings. The caller must have `DEPLOY_SUCKERS` permission, and this registry must hold
507
- /// `MAP_SUCKER_TOKEN` permission for the project.
481
+ /// its deployer, registered in this registry, and immediately configured with its token mappings. Multiple suckers
482
+ /// targeting the same peer chain are allowed for bridge resilience. The caller must have `DEPLOY_SUCKERS`
483
+ /// permission, and this registry must hold `MAP_SUCKER_TOKEN` permission for the project.
508
484
  /// @param projectId The ID of the project to deploy suckers for.
509
485
  /// @param salt The salt used to deploy the contract. For the suckers to be peers, this must be the same value on
510
486
  /// each chain where suckers are deployed.
@@ -551,10 +527,6 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
551
527
  .createForSender({localProjectId: projectId, salt: salt, peer: configuration.peer});
552
528
  suckers[i] = address(sucker);
553
529
 
554
- // Make sure no active sucker already targets the same peer chain.
555
- // slither-disable-next-line calls-loop
556
- _revertIfDuplicatePeerChain({projectId: projectId, newSucker: sucker});
557
-
558
530
  // Store the sucker as being deployed for this project.
559
531
  // slither-disable-next-line unused-return
560
532
  _suckersOf[projectId].set({key: address(sucker), value: _SUCKER_EXISTS});
@@ -121,8 +121,9 @@ contract JBSwapCCIPSucker is JBCCIPSucker, IUnlockCallback, IUniswapV3SwapCallba
121
121
  /// @notice The Uniswap V3 factory for pool discovery and callback verification. Can be address(0).
122
122
  IUniswapV3Factory public immutable V3_FACTORY;
123
123
 
124
- /// @notice The wrapped native token (e.g., WETH on Ethereum). Used for V3 native swaps.
125
- IWrappedNativeToken public immutable WETH;
124
+ /// @notice The ERC-20 wrapper for the chain's native token (e.g. WETH on Ethereum, WCELO on Celo). Used for V3
125
+ /// native swaps.
126
+ IWrappedNativeToken public immutable WRAPPED_NATIVE_TOKEN;
126
127
 
127
128
  //*********************************************************************//
128
129
  // ------------------- internal stored properties -------------------- //
@@ -184,7 +185,7 @@ contract JBSwapCCIPSucker is JBCCIPSucker, IUnlockCallback, IUniswapV3SwapCallba
184
185
  // ------------------- transient stored properties ------------------- //
185
186
  //*********************************************************************//
186
187
 
187
- /// @notice Leaf index + 1 of the claim currently being processed (set by `claim` override).
188
+ /// @notice Leaf index + 1 of the claim currently in progress (set by the `claim` override).
188
189
  /// @dev Transient storage — auto-resets to 0 each transaction, saving ~9,800 gas per claim vs SSTORE.
189
190
  /// Value 0 means no active claim (bypass scaling); non-zero means leafIndex = value - 1.
190
191
  uint256 transient _currentClaimLeafIndex;
@@ -223,11 +224,11 @@ contract JBSwapCCIPSucker is JBCCIPSucker, IUnlockCallback, IUniswapV3SwapCallba
223
224
  POOL_MANAGER = swapDeployer.poolManager();
224
225
  V3_FACTORY = swapDeployer.v3Factory();
225
226
  UNIV4_HOOK = swapDeployer.univ4Hook();
226
- WETH = IWrappedNativeToken(swapDeployer.weth());
227
+ WRAPPED_NATIVE_TOKEN = IWrappedNativeToken(swapDeployer.weth());
227
228
 
228
229
  if (address(BRIDGE_TOKEN) == address(0)) revert JBSwapCCIPSucker_InvalidBridgeToken();
229
- // BRIDGE_TOKEN must not be WETH native/WETH wrapping and CCIP ERC-20 bridging conflict.
230
- if (address(BRIDGE_TOKEN) == address(WETH) && address(WETH) != address(0)) {
230
+ // BRIDGE_TOKEN must not be the wrapped native token — wrapping and CCIP ERC-20 bridging conflict.
231
+ if (address(BRIDGE_TOKEN) == address(WRAPPED_NATIVE_TOKEN) && address(WRAPPED_NATIVE_TOKEN) != address(0)) {
231
232
  revert JBSwapCCIPSucker_InvalidBridgeToken();
232
233
  }
233
234
  // NOTE: V3_FACTORY and POOL_MANAGER can both be address(0) on chains where the local terminal token
@@ -239,7 +240,8 @@ contract JBSwapCCIPSucker is JBCCIPSucker, IUnlockCallback, IUniswapV3SwapCallba
239
240
  // ------------------------- receive / fallback ---------------------- //
240
241
  //*********************************************************************//
241
242
 
242
- /// @notice Allow this contract to receive ETH (from V4 swaps, WETH unwrap, and CCIP refunds).
243
+ /// @notice Allow this contract to receive native tokens (from V4 swaps, wrapped-native-token unwrap, and CCIP
244
+ /// refunds).
243
245
  receive() external payable override {}
244
246
 
245
247
  //*********************************************************************//
@@ -370,8 +372,8 @@ contract JBSwapCCIPSucker is JBCCIPSucker, IUnlockCallback, IUniswapV3SwapCallba
370
372
  }
371
373
 
372
374
  /// @notice Uniswap V3 swap callback — delegates to JBSwapPoolLib (via DELEGATECALL) to reduce bytecode.
373
- /// @param amount0Delta The amount of token0 being used for the swap.
374
- /// @param amount1Delta The amount of token1 being used for the swap.
375
+ /// @param amount0Delta The amount of token0 used for the swap.
376
+ /// @param amount1Delta The amount of token1 used for the swap.
375
377
  /// @param data Encoded (originalTokenIn, normalizedTokenIn, normalizedTokenOut).
376
378
  function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external override {
377
379
  JBSwapPoolLib.executeV3SwapCallback({
@@ -502,7 +504,7 @@ contract JBSwapCCIPSucker is JBCCIPSucker, IUnlockCallback, IUniswapV3SwapCallba
502
504
  /// Delegates CCIP message construction to JBCCIPLib (via DELEGATECALL) to reduce bytecode.
503
505
  /// @param transportPayment The ETH sent for CCIP fees.
504
506
  /// @param index The last leaf index in the current batch.
505
- /// @param token The local token being bridged.
507
+ /// @param token The local token to bridge.
506
508
  /// @param amount The amount of local tokens to bridge.
507
509
  /// @param remoteToken The remote token configuration (including minGas).
508
510
  /// @param sucker_message The merkle root message to send to the remote chain.
@@ -593,7 +595,10 @@ contract JBSwapCCIPSucker is JBCCIPSucker, IUnlockCallback, IUniswapV3SwapCallba
593
595
  function _executeSwap(address tokenIn, address tokenOut, uint256 amount) internal returns (uint256 amountOut) {
594
596
  return JBSwapPoolLib.executeSwap({
595
597
  config: JBSwapPoolLib.SwapConfig({
596
- v3Factory: V3_FACTORY, poolManager: POOL_MANAGER, univ4Hook: UNIV4_HOOK, weth: address(WETH)
598
+ v3Factory: V3_FACTORY,
599
+ poolManager: POOL_MANAGER,
600
+ univ4Hook: UNIV4_HOOK,
601
+ weth: address(WRAPPED_NATIVE_TOKEN)
597
602
  }),
598
603
  tokenIn: tokenIn,
599
604
  tokenOut: tokenOut,
@@ -22,7 +22,7 @@ contract JBCeloSuckerDeployer is JBOptimismSuckerDeployer, IJBCeloSuckerDeployer
22
22
  // ---------------------- public stored properties ------------------- //
23
23
  //*********************************************************************//
24
24
 
25
- /// @notice The wrapped native token (WETH) on the local chain.
25
+ /// @notice The ERC-20 wrapper for the chain's native token on the local chain.
26
26
  IWrappedNativeToken public override wrappedNative;
27
27
 
28
28
  //*********************************************************************//
@@ -63,7 +63,7 @@ contract JBCeloSuckerDeployer is JBOptimismSuckerDeployer, IJBCeloSuckerDeployer
63
63
  /// @notice Handles layer specific configuration including the wrapped native token.
64
64
  /// @param messenger The OPMessenger on this layer.
65
65
  /// @param bridge The OPStandardBridge on this layer.
66
- /// @param _wrappedNative The wrapped native token (WETH) on this layer.
66
+ /// @param _wrappedNative The ERC-20 wrapper for the chain's native token on this layer.
67
67
  function setChainSpecificConstants(
68
68
  IOPMessenger messenger,
69
69
  IOPStandardBridge bridge,
@@ -41,7 +41,7 @@ contract JBSwapCCIPSuckerDeployer is JBCCIPSuckerDeployer, IJBSwapCCIPSuckerDepl
41
41
  /// @notice The Uniswap V4 hook address for pool discovery (optional).
42
42
  address public univ4Hook;
43
43
 
44
- /// @notice The wrapped native token address (e.g., WETH).
44
+ /// @notice The ERC-20 wrapper address for the chain's native token (e.g. WETH on Ethereum).
45
45
  address public weth;
46
46
 
47
47
  //*********************************************************************//
@@ -72,7 +72,7 @@ contract JBSwapCCIPSuckerDeployer is JBCCIPSuckerDeployer, IJBSwapCCIPSuckerDepl
72
72
  /// @param _poolManager The Uniswap V4 PoolManager (can be address(0) if V4 unavailable).
73
73
  /// @param _v3Factory The Uniswap V3 factory (can be address(0) if V3 unavailable).
74
74
  /// @param _univ4Hook The V4 hook for pool discovery (optional, address(0) if none).
75
- /// @param _weth The wrapped native token address (e.g., WETH).
75
+ /// @param _weth The ERC-20 wrapper address for the chain's native token (e.g. WETH on Ethereum).
76
76
  function setSwapConstants(
77
77
  IERC20 _bridgeToken,
78
78
  IPoolManager _poolManager,
@@ -10,7 +10,7 @@ import {IOPStandardBridge} from "./IOPStandardBridge.sol";
10
10
  interface IJBCeloSuckerDeployer is IJBOpSuckerDeployer {
11
11
  // View functions
12
12
 
13
- /// @notice The wrapped native token (WETH) on the local chain.
13
+ /// @notice The ERC-20 wrapper for the chain's native token on the local chain.
14
14
  function wrappedNative() external view returns (IWrappedNativeToken);
15
15
 
16
16
  // State-changing functions
@@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
4
4
  /// @notice Optional data-hook interface for adding project-specific adjusted accounts to peer-chain snapshots.
5
5
  interface IJBPeerChainAdjustedAccounts {
6
6
  /// @notice Extra supply, surplus, and balance that should be included in cross-chain peer snapshots.
7
- /// @param projectId The ID of the project being snapshotted.
7
+ /// @param projectId The ID of the project to snapshot.
8
8
  /// @param decimals The decimals the returned surplus and balance should use.
9
9
  /// @param currency The currency the returned surplus and balance should be in terms of.
10
10
  /// @return supply The extra supply to include in `sourceTotalSupply`.
@@ -61,8 +61,8 @@ interface IJBSucker is IERC165 {
61
61
  event NewInboxTreeRoot(address indexed token, uint64 nonce, bytes32 root, address caller);
62
62
 
63
63
  /// @notice Emitted when the outbox tree root and bridged assets are sent to the remote peer.
64
- /// @param root The outbox tree root being sent.
65
- /// @param token The terminal token being bridged.
64
+ /// @param root The outbox tree root sent to the remote peer.
65
+ /// @param token The terminal token to bridge.
66
66
  /// @param index The current outbox tree index.
67
67
  /// @param nonce The nonce assigned to this root message.
68
68
  /// @param caller The address that initiated the send.
@@ -22,6 +22,7 @@ interface IJBSwapCCIPSuckerDeployer is IJBCCIPSuckerDeployer {
22
22
  /// @notice The Uniswap V4 hook address used during pool discovery (optional).
23
23
  function univ4Hook() external view returns (address);
24
24
 
25
- /// @notice The wrapped native token address (e.g., WETH). Used for V3 native swaps.
25
+ /// @notice The ERC-20 wrapper address for the chain's native token (e.g. WETH on Ethereum). Used for V3 native
26
+ /// swaps.
26
27
  function weth() external view returns (address);
27
28
  }
@@ -7,7 +7,7 @@ interface IL1ArbitrumGateway {
7
7
  /// @param _token The L1 token address.
8
8
  /// @param _from The sender on L1.
9
9
  /// @param _to The recipient on L2.
10
- /// @param _amount The amount of tokens being bridged.
10
+ /// @param _amount The amount of tokens to bridge.
11
11
  /// @param _data Additional data (forwarded to the L2 gateway).
12
12
  /// @return The ABI-encoded calldata for `finalizeInboundTransfer` on the L2 gateway.
13
13
  function getOutboundCalldata(
@@ -61,7 +61,7 @@ library CCIPHelper {
61
61
  address public constant TEMPO_LINK = 0x15C03488B29e27d62BAf10E30b0c474bf60E0264;
62
62
  address public constant TEMPO_MOD_LINK = 0xEAB080c724587fFC9F2EFF82e36EE4Fb27774959;
63
63
 
64
- /// @notice The WETH address of each chain
64
+ /// @notice The wrapped native token address of each chain
65
65
  address public constant ETH_WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
66
66
  address public constant ETH_SEP_WETH = 0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534;
67
67
  address public constant OP_WETH = 0x4200000000000000000000000000000000000006;
@@ -146,9 +146,9 @@ library CCIPHelper {
146
146
  }
147
147
  }
148
148
 
149
- /// @notice Returns the WETH address for a given chain ID.
149
+ /// @notice Returns the wrapped native token address for a given chain ID.
150
150
  /// @param chainId The EVM chain ID to look up.
151
- /// @return weth The WETH address.
151
+ /// @return weth The wrapped native token address.
152
152
  function wethOfChain(uint256 chainId) public pure returns (address weth) {
153
153
  if (chainId == ETH_ID) {
154
154
  return ETH_WETH;
@@ -19,13 +19,13 @@ library JBCCIPLib {
19
19
  // ---------------------- external transactions ---------------------- //
20
20
  //*********************************************************************//
21
21
 
22
- /// @notice Prepare token amounts for CCIP: wrap native ETH -> WETH, build token amounts array, approve router.
22
+ /// @notice Prepare token amounts for CCIP: wrap native tokens, build token amounts array, approve router.
23
23
  /// @dev Runs via DELEGATECALL so native ETH wrapping uses the caller's balance.
24
24
  /// @param ccipRouter The CCIP router.
25
25
  /// @param token The token to bridge (may be NATIVE_TOKEN).
26
26
  /// @param amount The amount to bridge.
27
27
  /// @return tokenAmounts The CCIP token amounts array (length 0 or 1).
28
- /// @return bridgeToken The actual ERC-20 token address being bridged (WETH if native was wrapped).
28
+ /// @return bridgeToken The actual ERC-20 token address to bridge (wrapped native token if native was wrapped).
29
29
  function prepareTokenAmounts(
30
30
  ICCIPRouter ccipRouter,
31
31
  address token,
@@ -42,13 +42,13 @@ library JBCCIPLib {
42
42
  // Start with the original token as the bridge token.
43
43
  bridgeToken = token;
44
44
 
45
- // Wrap native ETH -> WETH for CCIP bridging. CCIP only transports ERC-20s.
45
+ // Wrap native tokens for CCIP bridging. CCIP only transports ERC-20s.
46
46
  if (token == JBConstants.NATIVE_TOKEN) {
47
47
  // Get the wrapped native token address from the CCIP router.
48
48
  // slither-disable-next-line calls-loop
49
49
  IWrappedNativeToken wrappedNative = ccipRouter.getWrappedNative();
50
50
 
51
- // Deposit ETH to receive WETH.
51
+ // Deposit native tokens to receive wrapped native tokens.
52
52
  // slither-disable-next-line calls-loop,arbitrary-send-eth
53
53
  wrappedNative.deposit{value: amount}();
54
54
 
@@ -157,8 +157,8 @@ library JBCCIPLib {
157
157
  }
158
158
  }
159
159
 
160
- /// @notice Unwrap WETH -> ETH from received CCIP tokens if the delivered token is the router's wrapped native.
161
- /// @dev Runs via DELEGATECALL so `address(this).balance` refers to the calling contract.
160
+ /// @notice Unwrap wrapped native tokens from received CCIP tokens if the delivered token matches the wrapped
161
+ /// native. @dev Runs via DELEGATECALL so `address(this).balance` refers to the calling contract.
162
162
  /// @param ccipRouter The CCIP router (used to look up wrapped native token).
163
163
  /// @param destTokenAmounts The token amounts delivered by CCIP (length 0 or 1).
164
164
  function unwrapReceivedTokens(ICCIPRouter ccipRouter, Client.EVMTokenAmount[] calldata destTokenAmounts) external {
@@ -171,12 +171,12 @@ library JBCCIPLib {
171
171
  // slither-disable-next-line calls-loop
172
172
  IWrappedNativeToken wrappedNative = ccipRouter.getWrappedNative();
173
173
 
174
- // If the delivered token is WETH and the amount is non-zero, unwrap it.
174
+ // If the delivered token is the wrapped native token and the amount is non-zero, unwrap it.
175
175
  if (tokenAmount.token == address(wrappedNative) && tokenAmount.amount > 0) {
176
176
  // Record the ETH balance before unwrapping.
177
177
  uint256 balanceBefore = address(this).balance;
178
178
 
179
- // Withdraw WETH to receive ETH.
179
+ // Withdraw wrapped native tokens to receive native tokens.
180
180
  wrappedNative.withdraw(tokenAmount.amount);
181
181
 
182
182
  // Assert the ETH balance increased by the expected amount.
@@ -19,7 +19,7 @@ library JBRelayBeneficiary {
19
19
  /// @dev Returns `beneficiary` unchanged if the payer is not a registered sucker or if no relay data is found.
20
20
  /// @param payer The address that called `terminal.pay()` (i.e. `context.payer`).
21
21
  /// @param beneficiary The beneficiary set in the payment context (i.e. `context.beneficiary`).
22
- /// @param projectId The project being paid.
22
+ /// @param projectId The project to pay.
23
23
  /// @param metadata The payment metadata (`context.payerMetadata` or `context.metadata`).
24
24
  /// @param registry The sucker registry used to verify that `payer` is a legitimate sucker.
25
25
  /// @return effectiveBeneficiary The resolved beneficiary — the relay address if valid, or the original.
@@ -227,7 +227,7 @@ library JBSuckerLib {
227
227
  /// @param prices The price oracle to use for non-ETH terminal-token balances.
228
228
  /// @param projectId The project ID.
229
229
  /// @param remoteToken The remote token bytes32 address.
230
- /// @param amount The amount of terminal tokens being bridged.
230
+ /// @param amount The amount of terminal tokens to bridge.
231
231
  /// @param nonce The outbox nonce for this send.
232
232
  /// @param root The merkle root of the outbox tree.
233
233
  /// @param messageVersion The message format version.
@@ -269,8 +269,8 @@ library JBSuckerLib {
269
269
  /// @notice Optional project-specific adjusted accounts to add to peer-chain snapshots.
270
270
  /// @dev Reads the current ruleset's data hook and asks it for extra supply/surplus. Non-supporting hooks,
271
271
  /// broken hooks, and short return data are ignored so a project's baseline snapshot remains usable.
272
- /// @param controller The controller for the project being snapshotted.
273
- /// @param projectId The project being snapshotted.
272
+ /// @param controller The controller for the project to snapshot.
273
+ /// @param projectId The project to snapshot.
274
274
  /// @return additionalSupply The supply to add to `sourceTotalSupply`.
275
275
  /// @return additionalSurplus The surplus to add to `sourceSurplus`, denominated in ETH at 18 decimals.
276
276
  /// @return additionalBalance The balance to add to `sourceBalance`, denominated in ETH at 18 decimals.
@@ -308,7 +308,7 @@ library JBSuckerLib {
308
308
  /// @notice Builds the local accounting values used in outbound peer-chain snapshots.
309
309
  /// @param directory The JB directory to look up controllers and terminals.
310
310
  /// @param prices The price oracle to use for non-ETH terminal-token balances.
311
- /// @param projectId The project being snapshotted.
311
+ /// @param projectId The project to snapshot.
312
312
  /// @return localTotalSupply The total project token supply, including reserved tokens.
313
313
  /// @return ethSurplus The terminal surplus denominated in ETH at 18 decimals.
314
314
  /// @return ethBalance The terminal balance denominated in ETH at 18 decimals.
@@ -54,7 +54,7 @@ library JBSwapLib {
54
54
  //*********************************************************************//
55
55
 
56
56
  /// @notice Estimate the price impact of a swap, scaled by IMPACT_PRECISION.
57
- /// @param amountIn The amount of tokens being swapped in.
57
+ /// @param amountIn The amount of tokens to swap in.
58
58
  /// @param liquidity The pool's in-range liquidity.
59
59
  /// @param sqrtP The sqrt price in Q96 format.
60
60
  /// @param zeroForOne Whether the swap is token0 -> token1.
@@ -84,7 +84,7 @@ library JBSwapLib {
84
84
 
85
85
  /// @notice Compute a sqrtPriceLimitX96 from input/output amounts so the swap stops
86
86
  /// if the execution price would be worse than the minimum acceptable rate.
87
- /// @param amountIn The amount of tokens being swapped in.
87
+ /// @param amountIn The amount of tokens to swap in.
88
88
  /// @param minimumAmountOut The minimum acceptable output.
89
89
  /// @param zeroForOne True when selling token0 for token1 (price decreases).
90
90
  /// @return sqrtPriceLimit The V3-compatible sqrtPriceLimitX96.
@@ -77,7 +77,7 @@ library JBSwapPoolLib {
77
77
  /// @custom:member v3Factory The Uniswap V3 factory used for pool discovery.
78
78
  /// @custom:member poolManager The Uniswap V4 pool manager used for V4 pool queries and swaps.
79
79
  /// @custom:member univ4Hook The address of the Uniswap V4 hook contract to search for hooked pools.
80
- /// @custom:member weth The address of the wrapped native token (WETH) on this chain.
80
+ /// @custom:member weth The address of the ERC-20 wrapper for the chain's native token (e.g. WETH on Ethereum).
81
81
  struct SwapConfig {
82
82
  IUniswapV3Factory v3Factory;
83
83
  IPoolManager poolManager;
@@ -91,7 +91,7 @@ library JBSwapPoolLib {
91
91
 
92
92
  /// @notice Execute a full swap: discover the best V3/V4 pool, quote via TWAP, execute the swap.
93
93
  /// @dev Runs via DELEGATECALL so the calling contract's balance and callbacks are used.
94
- /// @param config The swap configuration (factory, pool manager, hook, WETH addresses).
94
+ /// @param config The swap configuration (factory, pool manager, hook, wrapped native token addresses).
95
95
  /// @param tokenIn The input token (raw address, may be NATIVE_TOKEN sentinel).
96
96
  /// @param tokenOut The output token (raw address).
97
97
  /// @param amount The amount of input tokens to swap.
@@ -108,11 +108,11 @@ library JBSwapPoolLib {
108
108
  external
109
109
  returns (uint256 amountOut)
110
110
  {
111
- // Normalize NATIVE_TOKEN sentinel to WETH for pool lookups.
111
+ // Normalize NATIVE_TOKEN sentinel to the wrapped native token for pool lookups.
112
112
  address normalizedIn = _normalize({token: tokenIn, weth: config.weth});
113
113
  address normalizedOut = _normalize({token: tokenOut, weth: config.weth});
114
114
 
115
- // No swap needed if tokens are the same after normalization (e.g., NATIVE_TOKEN and WETH).
115
+ // No swap needed if tokens are the same after normalization (e.g., NATIVE_TOKEN and wrapped native token).
116
116
  if (normalizedIn == normalizedOut) return amount;
117
117
 
118
118
  // Discover the most liquid pool across V3 and V4.
@@ -163,16 +163,16 @@ library JBSwapPoolLib {
163
163
  originalTokenIn: tokenIn
164
164
  });
165
165
  }
166
- // V3 outputs WETH for native pairs — unwrap to raw ETH.
166
+ // V3 outputs wrapped native token for native pairs — unwrap to raw native token.
167
167
  if (tokenOut == JBConstants.NATIVE_TOKEN) {
168
168
  IWrappedNativeToken(config.weth).withdraw(amountOut);
169
169
  }
170
170
  }
171
171
 
172
- // V4 outputs native ETH for WETH-paired pools. If the caller requested WETH (not NATIVE_TOKEN),
173
- // wrap the received ETH so the caller gets the token they expect.
172
+ // V4 outputs native tokens for wrapped-native-paired pools. If the caller requested the wrapped form
173
+ // (not NATIVE_TOKEN), wrap the received native tokens so the caller gets the token they expect.
174
174
  if (isV4 && tokenOut != JBConstants.NATIVE_TOKEN && normalizedOut == config.weth) {
175
- // Wrap through the configured WETH contract; this is not a user-selected ETH recipient.
175
+ // Wrap through the configured wrapped native token contract.
176
176
  // slither-disable-next-line arbitrary-send-eth
177
177
  IWrappedNativeToken(config.weth).deposit{value: amountOut}();
178
178
  }
@@ -236,7 +236,7 @@ library JBSwapPoolLib {
236
236
  // Settle input (pay what we owe to the PoolManager).
237
237
  Currency inputCurrency = zeroForOne ? key.currency0 : key.currency1;
238
238
  if (Currency.unwrap(inputCurrency) == address(0)) {
239
- // Native ETH: unwrap WETH if needed, then settle by sending ETH value directly.
239
+ // Native token: unwrap if needed, then settle by sending native value directly.
240
240
  if (weth != address(0)) IWrappedNativeToken(weth).withdraw(amountIn);
241
241
  // slither-disable-next-line unused-return,arbitrary-send-eth
242
242
  poolManager.settle{value: amountIn}();
@@ -260,8 +260,8 @@ library JBSwapPoolLib {
260
260
  /// `uniswapV3SwapCallback` so the V3 callback logic lives in library bytecode.
261
261
  /// @dev DELEGATECALL preserves msg.sender (the V3 pool), allowing pool verification.
262
262
  /// @param v3Factory The Uniswap V3 factory for pool verification.
263
- /// @param amount0Delta The amount of token0 being used for the swap.
264
- /// @param amount1Delta The amount of token1 being used for the swap.
263
+ /// @param amount0Delta The amount of token0 used for the swap.
264
+ /// @param amount1Delta The amount of token1 used for the swap.
265
265
  /// @param data Encoded (originalTokenIn, normalizedTokenIn, normalizedTokenOut).
266
266
  function executeV3SwapCallback(
267
267
  IUniswapV3Factory v3Factory,
@@ -286,8 +286,8 @@ library JBSwapPoolLib {
286
286
  // forge-lint: disable-next-line(unsafe-typecast)
287
287
  uint256 amountToSend = amount0Delta < 0 ? uint256(amount1Delta) : uint256(amount0Delta);
288
288
 
289
- // If input is native ETH, wrap to WETH for V3.
290
- // When originalTokenIn == NATIVE_TOKEN, normalizedIn is already the WETH address.
289
+ // If input is the native token, wrap for V3.
290
+ // When originalTokenIn == NATIVE_TOKEN, normalizedIn is already the wrapped native address.
291
291
  if (originalTokenIn == JBConstants.NATIVE_TOKEN) {
292
292
  IWrappedNativeToken(normalizedIn).deposit{value: amountToSend}();
293
293
  }
@@ -302,7 +302,7 @@ library JBSwapPoolLib {
302
302
 
303
303
  /// @notice Externally accessible pool discovery for testing and off-chain queries.
304
304
  /// @param config The swap configuration (factory, pool manager, etc.).
305
- /// @param normalizedTokenIn The normalized input token address (WETH, not NATIVE_TOKEN).
305
+ /// @param normalizedTokenIn The normalized input token address (wrapped native token, not NATIVE_TOKEN).
306
306
  /// @param normalizedTokenOut The normalized output token address.
307
307
  /// @return isV4 Whether the best pool is a V4 pool.
308
308
  /// @return v3Pool The best V3 pool (or address(0) if V4 is better).
@@ -327,8 +327,8 @@ library JBSwapPoolLib {
327
327
  //*********************************************************************//
328
328
 
329
329
  /// @notice Find the highest liquidity pool across all V3 fee tiers and V4 pool configurations.
330
- /// @param config The swap configuration (factory, pool manager, hook, WETH addresses).
331
- /// @param normalizedTokenIn The normalized input token address (WETH, not NATIVE_TOKEN).
330
+ /// @param config The swap configuration (factory, pool manager, hook, wrapped native token addresses).
331
+ /// @param normalizedTokenIn The normalized input token address (wrapped native token, not NATIVE_TOKEN).
332
332
  /// @param normalizedTokenOut The normalized output token address.
333
333
  /// @return isV4 Whether the best pool is a V4 pool.
334
334
  /// @return v3Pool The best V3 pool (or address(0) if V4 is better).
@@ -419,7 +419,7 @@ library JBSwapPoolLib {
419
419
 
420
420
  /// @notice Search V4 pools across 4 fee tiers and 2 hook configs for the best eligible liquidity.
421
421
  /// @dev TWAP-capable hooked pools are preferred over hookless spot pools. Broken hooked pools are skipped.
422
- /// @param config The swap configuration (pool manager, hook, WETH addresses).
422
+ /// @param config The swap configuration (pool manager, hook, wrapped native token addresses).
423
423
  /// @param normalizedTokenIn The normalized input token address.
424
424
  /// @param normalizedTokenOut The normalized output token address.
425
425
  /// @return bestKey The selected V4 pool key.
@@ -439,8 +439,8 @@ library JBSwapPoolLib {
439
439
  PoolKey memory bestSpotKey;
440
440
  uint128 bestSpotLiquidity;
441
441
 
442
- // Convert to V4 convention before sorting: WETH represents native ETH in the calling code, while V4 pool
443
- // keys use address(0) for native ETH.
442
+ // Convert to V4 convention before sorting: the wrapped native token represents native tokens in the calling
443
+ // code, while V4 pool keys use address(0) for native tokens.
444
444
  address sorted0;
445
445
  address sorted1;
446
446
  {
@@ -604,7 +604,7 @@ library JBSwapPoolLib {
604
604
  }
605
605
 
606
606
  /// @notice Get a V4 quote with dynamic slippage. Hooked pools must serve TWAP; hookless pools use spot fallback.
607
- /// @param config The swap configuration (pool manager, WETH addresses).
607
+ /// @param config The swap configuration (pool manager, wrapped native token addresses).
608
608
  /// @param key The V4 pool key to quote against.
609
609
  /// @param normalizedTokenIn The normalized input token address.
610
610
  /// @param normalizedTokenOut The normalized output token address.
@@ -867,7 +867,7 @@ library JBSwapPoolLib {
867
867
  //*********************************************************************//
868
868
 
869
869
  /// @notice Quote via V4 TWAP/spot and execute swap. Separate function for stack isolation.
870
- /// @param config The swap configuration (pool manager, WETH addresses).
870
+ /// @param config The swap configuration (pool manager, wrapped native token addresses).
871
871
  /// @param key The V4 pool key to swap through.
872
872
  /// @param normalizedTokenIn The normalized input token address.
873
873
  /// @param normalizedTokenOut The normalized output token address.
@@ -976,7 +976,7 @@ library JBSwapPoolLib {
976
976
  }
977
977
 
978
978
  /// @notice Execute a swap through a V4 pool via `PoolManager.unlock()`.
979
- /// @param config The swap configuration (pool manager, WETH addresses).
979
+ /// @param config The swap configuration (pool manager, wrapped native token addresses).
980
980
  /// @param key The V4 pool key to swap through.
981
981
  /// @param normalizedTokenIn The normalized input token address.
982
982
  /// @param amount The amount of input tokens to swap.
@@ -992,7 +992,7 @@ library JBSwapPoolLib {
992
992
  internal
993
993
  returns (uint256 amountOut)
994
994
  {
995
- // Convert WETH to address(0) for V4's native ETH convention.
995
+ // Convert wrapped native token to address(0) for V4's native token convention.
996
996
  address v4In = normalizedTokenIn == config.weth ? address(0) : normalizedTokenIn;
997
997
 
998
998
  // Determine swap direction based on currency ordering in the pool key.
@@ -1021,9 +1021,9 @@ library JBSwapPoolLib {
1021
1021
  amountOut = abi.decode(result, (uint256));
1022
1022
  }
1023
1023
 
1024
- /// @notice Normalize a token address, converting the NATIVE_TOKEN sentinel to WETH.
1024
+ /// @notice Normalize a token address, converting the NATIVE_TOKEN sentinel to the wrapped native token.
1025
1025
  /// @param token The token address to normalize.
1026
- /// @param weth The WETH address on this chain.
1026
+ /// @param weth The wrapped native token address on this chain.
1027
1027
  /// @return The normalized token address.
1028
1028
  function _normalize(address token, address weth) internal pure returns (address) {
1029
1029
  return token == JBConstants.NATIVE_TOKEN ? weth : token;
@@ -6,7 +6,7 @@ import {JBInboxTreeRoot} from "./JBInboxTreeRoot.sol";
6
6
  /// @notice Information about the remote (inbox) tree's root, passed in a message from the remote chain.
7
7
  /// @custom:member version The message format version. Used to reject incompatible messages.
8
8
  /// @custom:member token The remote token address (bytes32 for cross-VM compatibility with SVM).
9
- /// @custom:member amount The amount of tokens being sent.
9
+ /// @custom:member amount The amount of tokens to send.
10
10
  /// @custom:member remoteRoot The root of the merkle tree.
11
11
  /// @custom:member sourceTotalSupply The total token supply (including reserved tokens) on the source chain at the
12
12
  /// time the message was sent. Used by the receiving chain to track cross-chain supply for cash out tax calculations.