@bananapus/suckers-v6 0.0.72 → 0.0.73

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/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  - [AUDIT_INSTRUCTIONS.md](./AUDIT_INSTRUCTIONS.md) — scope, entrypoints, and reading order for security review.
14
14
  - [SKILLS.md](./SKILLS.md) — reusable patterns and gotchas distilled from this codebase.
15
15
  - [STYLE_GUIDE.md](./STYLE_GUIDE.md) — Solidity conventions used across this repo.
16
- - [CHANGELOG.md](./CHANGELOG.md) versioned change history.
16
+ - [CHANGELOG.md](./CHANGELOG.md) - V5 to V6 migration changelog.
17
17
 
18
18
  The codebase includes multiple bridge variants, but the canonical deployment and discovery tooling in this repo is narrower than the full runtime surface. Treat the deployment scripts and helper libraries as the source of truth for what is operationally supported today.
19
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/suckers-v6",
3
- "version": "0.0.72",
3
+ "version": "0.0.73",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,7 +11,8 @@
11
11
  "references/",
12
12
  "remappings.txt",
13
13
  "script/",
14
- "src/"
14
+ "src/",
15
+ "!src/archive/"
15
16
  ],
16
17
  "engines": {
17
18
  "node": ">=20.0.0"
@@ -26,18 +27,18 @@
26
27
  },
27
28
  "dependencies": {
28
29
  "@arbitrum/nitro-contracts": "3.2.0",
29
- "@bananapus/core-v6": "^0.0.81",
30
- "@bananapus/permission-ids-v6": "^0.0.28",
30
+ "@bananapus/core-v6": "^0.0.82",
31
+ "@bananapus/permission-ids-v6": "^0.0.30",
31
32
  "@chainlink/contracts-ccip": "1.6.4",
32
- "@chainlink/local": "0.2.7",
33
33
  "@openzeppelin/contracts": "5.6.1",
34
- "@prb/math": "4.1.1",
35
- "@uniswap/v3-core": "github:Uniswap/v3-core#6562c52e8f75f0c10f9deaf44861847585fc8129",
36
- "@uniswap/v3-periphery": "github:Uniswap/v3-periphery#b325bb0905d922ae61fcc7df85ee802e8df5e96c",
34
+ "@prb/math": "4.1.2",
37
35
  "@uniswap/v4-core": "1.0.2",
38
36
  "solady": "0.1.26"
39
37
  },
40
38
  "devDependencies": {
39
+ "@chainlink/local": "0.2.9",
40
+ "@uniswap/v3-core": "1.0.1",
41
+ "@uniswap/v3-periphery": "1.4.4",
41
42
  "@sphinx-labs/plugins": "0.33.3"
42
43
  }
43
44
  }
package/src/JBSucker.sol CHANGED
@@ -311,10 +311,9 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
311
311
  /// @dev A zero value preserves the default same-address deterministic peer.
312
312
  bytes32 private _peer;
313
313
 
314
- /// @notice The peer chain's per-currency surplus and balance from the latest snapshot. Rebuilt in full each time a
315
- /// fresher snapshot is received, so a context that dropped out of the new snapshot is simply absent — no
316
- /// per-entry
317
- /// versioning or clearing is needed. A read sums these and values them into the requested currency.
314
+ /// @notice The peer chain's per-currency surplus and balance from the latest snapshot.
315
+ /// @dev Rebuilt from each fresher snapshot; dropped contexts are absent without per-entry versioning or clearing.
316
+ /// A read sums these and values them into the requested currency.
318
317
  JBPeerChainContext[] private _peerContexts;
319
318
 
320
319
  //*********************************************************************//
@@ -645,8 +644,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
645
644
 
646
645
  /// @notice Configure which remote-chain tokens each local terminal token maps to, enabling (or disabling) those
647
646
  /// tokens for cross-chain bridging. Setting a remote token to `bytes32(0)` disables bridging and flushes any
648
- /// pending outbox entries. Requires `MAP_SUCKER_TOKEN` permission from the project owner (or called by the
649
- /// registry during deployment).
647
+ /// pending outbox entries. Requires `MAP_SUCKER_TOKEN` permission from the project owner or deployment registry.
650
648
  /// @param maps A list of local and remote terminal token addresses to map, and minimum amount/gas limits for
651
649
  /// bridging them.
652
650
  function mapTokens(JBTokenMapping[] calldata maps) external payable override {
@@ -705,8 +703,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
705
703
  /// For EVM peers: the EVM address left-padded to 32 bytes via `_toBytes32`.
706
704
  /// For SVM peers: the full 32-byte Solana public key.
707
705
  /// @param minTokensReclaimed The minimum amount of terminal tokens to cash out for. If the amount cashed out is
708
- /// less
709
- /// than this, the transaction will revert.
706
+ /// less than this, the transaction will revert.
710
707
  /// @param token The address of the terminal token to cash out for.
711
708
  function prepare(
712
709
  uint256 projectTokenCount,
@@ -904,9 +901,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
904
901
  }
905
902
 
906
903
  /// @notice The peer chain total supply bundled with the peer chain ID and snapshot freshness key.
907
- /// @dev Lets aggregators (e.g. `JBSuckerRegistry`) read the value, the peer chain it belongs to, and its
908
- /// freshness in one call instead of three separate staticcalls. The `value` is identical to
909
- /// `peerChainTotalSupply`.
904
+ /// @dev Lets aggregators (e.g. `JBSuckerRegistry`) read the value, peer chain, and freshness in one call instead
905
+ /// of three separate staticcalls. The `value` is identical to `peerChainTotalSupply`.
910
906
  /// @return A `JBPeerChainValue` with the total supply, peer chain ID, and snapshot freshness key.
911
907
  function peerChainTotalSupplyValue() external view returns (JBPeerChainValue memory) {
912
908
  return JBPeerChainValue({
@@ -1074,8 +1070,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1074
1070
  deployer = _msgSender();
1075
1071
  }
1076
1072
 
1077
- /// @notice Map an ERC-20 token on the local chain to an ERC-20 token on the remote chain, allowing that token to be
1078
- /// bridged.
1073
+ /// @notice Map an ERC-20 token on the local chain to a remote-chain ERC-20 token for bridging.
1079
1074
  /// @param map The local and remote terminal token addresses to map, and minimum amount/gas limits for bridging
1080
1075
  /// them.
1081
1076
  function mapToken(JBTokenMapping calldata map) public payable override {
@@ -1220,8 +1215,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1220
1215
  /// @return valid Whether the sender is the remote peer.
1221
1216
  function _isRemotePeer(address sender) internal virtual returns (bool valid);
1222
1217
 
1223
- /// @notice Map an ERC-20 token on the local chain to an ERC-20 token on the remote chain, allowing that token to be
1224
- /// bridged or disabled.
1218
+ /// @notice Map an ERC-20 token on the local chain to a remote-chain ERC-20 token, or disable bridging.
1225
1219
  /// @dev Once a token has outbox tree entries (`_outboxOf[token].tree.count != 0`), it cannot be remapped to a
1226
1220
  /// different remote token -- it can only be disabled by mapping to `address(0)`, which triggers a final root
1227
1221
  /// flush to settle outstanding claims. This permanence prevents double-spending: if a remapping were allowed
@@ -156,8 +156,7 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
156
156
  return exists && (val == _SUCKER_EXISTS || val == _SUCKER_DEPRECATED);
157
157
  }
158
158
 
159
- /// @notice Values one sucker's raw peer-chain balance into a currency, bundled with the peer chain ID and
160
- /// freshness.
159
+ /// @notice Values one sucker's raw peer-chain balance into a currency with peer chain ID and freshness.
161
160
  /// @dev Exposed as an external self-call boundary so `totalRemoteBalanceOf` can `try` it and drop a single sucker
162
161
  /// whose price feed is missing. A context whose currency already matches `currency` folds in at par (no feed read);
163
162
  /// a missing cross-currency feed reverts, and the aggregator catches it and skips just this sucker.
@@ -206,8 +205,7 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
206
205
  return JBPeerChainValue({value: value, peerChainId: chainId, snapshotTimestamp: snapshot});
207
206
  }
208
207
 
209
- /// @notice Values one sucker's raw peer-chain surplus into a currency, bundled with the peer chain ID and
210
- /// freshness.
208
+ /// @notice Values one sucker's raw peer-chain surplus into a currency with peer chain ID and freshness.
211
209
  /// @dev Exposed as an external self-call boundary so `totalRemoteSurplusOf` can `try` it and drop a single sucker
212
210
  /// whose price feed is missing. A context whose currency already matches `currency` folds in at par (no feed read);
213
211
  /// a missing cross-currency feed reverts, and the aggregator catches it and skips just this sucker.
@@ -222,8 +222,7 @@ interface IJBSucker is IERC165 {
222
222
  /// @param token The terminal token to cash out into.
223
223
  /// @param metadata Opaque caller-defined attribution payload included in the leaf hash. The sucker protocol does
224
224
  /// not inspect this value — it's covered by the merkle root, so the destination contract that consumes the claim
225
- /// can
226
- /// trust it once the proof verifies. Pass `bytes32(0)` for an ordinary bridge with no attribution context.
225
+ /// can trust it once the proof verifies. Pass `bytes32(0)` for an ordinary bridge with no attribution context.
227
226
  function prepare(
228
227
  uint256 projectTokenCount,
229
228
  bytes32 beneficiary,
@@ -62,8 +62,7 @@ interface IJBSuckerRegistry {
62
62
  /// @return The addresses of every sucker ever registered for `projectId`.
63
63
  function allSuckersOf(uint256 projectId) external view returns (address[] memory);
64
64
 
65
- /// @notice Returns true if the specified sucker belongs to the specified project and was deployed through this
66
- /// registry.
65
+ /// @notice Returns true if the specified sucker belongs to the project and was deployed through this registry.
67
66
  /// @param projectId The ID of the project to check for.
68
67
  /// @param addr The address of the sucker to check.
69
68
  /// @return Whether the sucker belongs to the project.
@@ -37,9 +37,7 @@ library JBSuckerLib {
37
37
 
38
38
  /// @notice Build the cross-chain snapshot message (total supply plus per-context surplus and balance).
39
39
  /// @dev Extracted from `JBSucker._buildSnapshotAndSend` to reduce child contract bytecode. Called via DELEGATECALL.
40
- /// The snapshot performs no price-feed valuation — it carries surplus and balance per context in each context's
41
- /// own
42
- /// currency.
40
+ /// The snapshot carries each context's surplus and balance in its own currency, without price-feed valuation.
43
41
  /// @param directory The JB directory to look up controllers and terminals.
44
42
  /// @param projectId The project ID.
45
43
  /// @param remoteToken The remote token bytes32 address.
@@ -311,11 +309,10 @@ library JBSuckerLib {
311
309
  }
312
310
 
313
311
  /// @notice Builds the local accounting values used in outbound peer-chain snapshots.
314
- /// @dev Project token supply stays a single currency-agnostic scalar. Surplus and balance are emitted per
315
- /// accounting context in each context's own currency, with no price-feed valuation the receiving chain folds
316
- /// each
317
- /// context into its same-asset local context at par. A project data hook may contribute additional supply plus its
318
- /// own per-context surplus/balance, appended to the terminal contexts.
312
+ /// @dev Project token supply stays a single currency-agnostic scalar. Surplus and balance are emitted per context
313
+ /// in that context's currency, with no price-feed valuation. The receiving chain folds each context into its
314
+ /// same-asset local context at par. A project data hook may contribute additional supply plus its own per-context
315
+ /// surplus/balance, appended to the terminal contexts.
319
316
  /// @param directory The JB directory to look up controllers and terminals.
320
317
  /// @param projectId The project to snapshot.
321
318
  /// @return localTotalSupply The total project token supply, including reserved tokens.
@@ -2,8 +2,7 @@
2
2
  pragma solidity ^0.8.0;
3
3
 
4
4
  /// @notice The root of an inbox tree for a given token in a `JBSucker`.
5
- /// @dev Inbox trees are used to receive from the remote chain to the local chain. Tokens can be `claim`ed from the
6
- /// inbox tree.
5
+ /// @dev Inbox trees are used to receive from the remote chain to the local chain. Tokens can be claimed from the tree.
7
6
  /// @custom:member nonce Tracks the nonce of the tree. The nonce cannot decrease.
8
7
  /// @custom:member root The root of the tree.
9
8
  struct JBInboxTreeRoot {
@@ -1,25 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.0;
3
-
4
- import {IJBOpSuckerDeployer} from "./IJBOpSuckerDeployer.sol";
5
- import {IWrappedNativeToken} from "./IWrappedNativeToken.sol";
6
- import {IOPMessenger} from "./IOPMessenger.sol";
7
- import {IOPStandardBridge} from "./IOPStandardBridge.sol";
8
-
9
- /// @notice Interface for a deployer of Celo-specific suckers (OP Stack with custom gas token).
10
- interface IJBCeloSuckerDeployer is IJBOpSuckerDeployer {
11
- // View functions
12
-
13
- /// @notice The ERC-20 wrapper for the chain's native token on the local chain.
14
- function wrappedNative() external view returns (IWrappedNativeToken);
15
-
16
- // State-changing functions
17
-
18
- /// @notice Set the chain-specific OP messenger, bridge, and wrapped native token constants.
19
- function setChainSpecificConstants(
20
- IOPMessenger messenger,
21
- IOPStandardBridge bridge,
22
- IWrappedNativeToken wrappedNative
23
- )
24
- external;
25
- }
@@ -1,28 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.0;
3
-
4
- import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5
- import {IUniswapV3Factory} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";
6
- import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
7
-
8
- import {IJBCCIPSuckerDeployer} from "./IJBCCIPSuckerDeployer.sol";
9
-
10
- /// @notice Interface for a deployer of swap-enabled CCIP suckers.
11
- /// @dev Extends the base CCIP deployer with Uniswap V3/V4 swap configuration for cross-currency bridging.
12
- interface IJBSwapCCIPSuckerDeployer is IJBCCIPSuckerDeployer {
13
- /// @notice The ERC-20 token used for CCIP bridging (e.g., USDC — exists on both chains).
14
- function bridgeToken() external view returns (IERC20);
15
-
16
- /// @notice The Uniswap V4 PoolManager. Can be address(0) if V4 is unavailable on this chain.
17
- function poolManager() external view returns (IPoolManager);
18
-
19
- /// @notice The Uniswap V3 factory. Can be address(0) if V3 is unavailable on this chain.
20
- function v3Factory() external view returns (IUniswapV3Factory);
21
-
22
- /// @notice The Uniswap V4 hook address used during pool discovery (optional).
23
- function univ4Hook() external view returns (address);
24
-
25
- /// @notice The ERC-20 wrapper address for the chain's native token (e.g. WETH on Ethereum). Used for V3 native
26
- /// swaps.
27
- function wrappedNativeToken() external view returns (address);
28
- }
@@ -1,188 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.28;
3
-
4
- import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
5
- import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
6
- import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
7
- import {IJBTokens} from "@bananapus/core-v6/src/interfaces/IJBTokens.sol";
8
- import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
9
- import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
10
- import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
11
-
12
- import {JBSucker} from "./JBSucker.sol";
13
- import {JBOptimismSucker} from "./JBOptimismSucker.sol";
14
- import {JBCeloSuckerDeployer} from "./deployers/JBCeloSuckerDeployer.sol";
15
- import {IJBSuckerRegistry} from "./interfaces/IJBSuckerRegistry.sol";
16
- import {IWrappedNativeToken} from "./interfaces/IWrappedNativeToken.sol";
17
- import {JBMessageRoot} from "./structs/JBMessageRoot.sol";
18
- import {JBRemoteToken} from "./structs/JBRemoteToken.sol";
19
- import {JBTokenMapping} from "./structs/JBTokenMapping.sol";
20
-
21
- /// @notice A `JBSucker` implementation for Celo — an OP Stack chain with a custom gas token (CELO, not ETH).
22
- /// @dev ETH exists on Celo only as an ERC-20. This sucker wraps native ETH before bridging
23
- /// as ERC-20 via the OP standard bridge, and removes the `NATIVE_TOKEN → NATIVE_TOKEN` restriction so that
24
- /// native ETH can map to a remote ERC-20.
25
- contract JBCeloSucker is JBOptimismSucker {
26
- //*********************************************************************//
27
- // --------------- public immutable stored properties ---------------- //
28
- //*********************************************************************//
29
-
30
- /// @notice The ERC-20 wrapper for the chain's native token on the local chain.
31
- IWrappedNativeToken public immutable WRAPPED_NATIVE_TOKEN;
32
-
33
- //*********************************************************************//
34
- // ---------------------------- constructor -------------------------- //
35
- //*********************************************************************//
36
-
37
- /// @param deployer A contract that deploys clones of this contract.
38
- /// @param directory A contract storing directories of terminals and controllers for each project.
39
- /// @param permissions A contract storing permissions.
40
- /// @param tokens A contract that manages token minting and burning.
41
- constructor(
42
- JBCeloSuckerDeployer deployer,
43
- IJBDirectory directory,
44
- IJBPermissions permissions,
45
- IJBTokens tokens,
46
- uint256 feeProjectId,
47
- IJBSuckerRegistry registry,
48
- address trustedForwarder
49
- )
50
- JBOptimismSucker(deployer, directory, permissions, tokens, feeProjectId, registry, trustedForwarder)
51
- {
52
- // Fetch the wrapped native token by doing a callback to the deployer contract.
53
- WRAPPED_NATIVE_TOKEN = JBCeloSuckerDeployer(deployer).wrappedNative();
54
- }
55
-
56
- //*********************************************************************//
57
- // ------------------------ external views --------------------------- //
58
- //*********************************************************************//
59
-
60
- /// @notice Returns the chain on which the peer is located.
61
- /// @return chainId of the peer.
62
- function peerChainId() external view virtual override returns (uint256) {
63
- uint256 chainId = block.chainid;
64
- if (chainId == 1) return 42_220;
65
- if (chainId == 42_220) return 1;
66
- return 0;
67
- }
68
-
69
- //*********************************************************************//
70
- // --------------------- internal transactions ----------------------- //
71
- //*********************************************************************//
72
-
73
- /// @notice Unwraps wrapped native tokens before adding to the project's balance.
74
- /// @dev When tokens are bridged from Celo → L1 via the OP bridge, wrapped native tokens (ERC-20) are released to
75
- /// the sucker. But the L1 project's terminal accepts native ETH (NATIVE_TOKEN), not the wrapped form. This override
76
- /// unwraps
77
- /// and adds native ETH to the project's balance.
78
- /// @param token The terminal token to add to the project's balance.
79
- /// @param amount The amount of terminal tokens to add to the project's balance.
80
- /// @param cachedProjectId The cached project ID to avoid redundant storage reads.
81
- function _addToBalance(address token, uint256 amount, uint256 cachedProjectId) internal override {
82
- if (token == address(WRAPPED_NATIVE_TOKEN)) {
83
- // Check addable amount against wrapped native token balance before unwrapping.
84
- uint256 addableAmount = amountToAddToBalanceOf(token);
85
- if (amount > addableAmount) {
86
- revert JBSucker_InsufficientBalance({amount: amount, balance: addableAmount});
87
- }
88
-
89
- // Unwrap wrapped native tokens → native tokens.
90
- WRAPPED_NATIVE_TOKEN.withdraw(amount);
91
-
92
- // Get the project's primary terminal for native token.
93
- IJBTerminal terminal =
94
- DIRECTORY.primaryTerminalOf({projectId: cachedProjectId, token: JBConstants.NATIVE_TOKEN});
95
-
96
- if (address(terminal) == address(0)) {
97
- revert JBSucker_NoTerminalForToken({projectId: cachedProjectId, token: JBConstants.NATIVE_TOKEN});
98
- }
99
-
100
- // Add native ETH to the project's balance.
101
- terminal.addToBalanceOf{value: amount}({
102
- projectId: cachedProjectId,
103
- token: JBConstants.NATIVE_TOKEN,
104
- amount: amount,
105
- shouldReturnHeldFees: false,
106
- memo: "",
107
- metadata: ""
108
- });
109
- } else {
110
- super._addToBalance({token: token, amount: amount, cachedProjectId: cachedProjectId});
111
- }
112
- }
113
-
114
- /// @notice Use the `OPMESSENGER` to send the outbox tree for the `token` and the corresponding funds to the peer
115
- /// over the `OPBRIDGE`.
116
- /// @dev For Celo, native ETH is wrapped and bridged as ERC-20. The messenger message is sent with
117
- /// `nativeValue = 0` because Celo's native token is CELO (not ETH), so we never attach ETH as msg.value.
118
- /// @param transportPayment the amount of `msg.value` that is going to get paid for sending this message.
119
- /// @param token The token to bridge the outbox tree for.
120
- /// @param remoteToken Information about the remote token to bridge to.
121
- // forge-lint: disable-next-line(mixed-case-function)
122
- function _sendRootOverAMB(
123
- uint256 transportPayment,
124
- uint256 index,
125
- address token,
126
- uint256 amount,
127
- JBRemoteToken memory remoteToken,
128
- JBMessageRoot memory message
129
- )
130
- internal
131
- override
132
- {
133
- index; // Silence unused parameter warning (not needed for Celo bridge).
134
-
135
- // Revert if there's a `msg.value`. The Celo bridge does not expect to be paid.
136
- if (transportPayment != 0) {
137
- revert JBSucker_UnexpectedMsgValue({value: transportPayment});
138
- }
139
-
140
- // Cache peer address to avoid redundant calls.
141
- address peerAddress = _toAddress(peer());
142
-
143
- if (amount != 0) {
144
- // Determine the local token to bridge — native ETH is wrapped first.
145
- address bridgeToken = token;
146
- if (token == JBConstants.NATIVE_TOKEN) {
147
- // Wrap native tokens so they can be bridged as ERC-20.
148
- WRAPPED_NATIVE_TOKEN.deposit{value: amount}();
149
- bridgeToken = address(WRAPPED_NATIVE_TOKEN);
150
- }
151
-
152
- // Approve the bridge to spend the token.
153
- SafeERC20.forceApprove({token: IERC20(bridgeToken), spender: address(OPBRIDGE), value: amount});
154
-
155
- // Bridge the ERC-20 token to the peer.
156
- OPBRIDGE.bridgeERC20To({
157
- localToken: bridgeToken,
158
- remoteToken: _toAddress(remoteToken.addr),
159
- to: peerAddress,
160
- amount: amount,
161
- minGasLimit: remoteToken.minGas,
162
- extraData: bytes("")
163
- });
164
-
165
- SafeERC20.forceApprove({token: IERC20(bridgeToken), spender: address(OPBRIDGE), value: 0});
166
- }
167
-
168
- // Send the messenger message with nativeValue = 0.
169
- // Celo's native token is CELO, not ETH — we never attach ETH as msg.value on the messenger.
170
- // On L1, the ETH was already wrapped and bridged as ERC-20 above.
171
- OPMESSENGER.sendMessage({
172
- target: peerAddress,
173
- message: abi.encodeCall(JBSucker.fromRemote, (message)),
174
- gasLimit: MESSENGER_BASE_GAS_LIMIT
175
- });
176
- }
177
-
178
- /// @notice Allow `NATIVE_TOKEN` to map to any remote token (not just `NATIVE_TOKEN`).
179
- /// @dev Celo uses CELO as native gas token. ETH is an ERC-20 on Celo. So `NATIVE_TOKEN` on L1
180
- /// maps to an ERC-20 address on Celo, not to `NATIVE_TOKEN`. The base class restriction is removed.
181
- function _validateTokenMapping(JBTokenMapping calldata map) internal pure virtual override {
182
- // Enforce a reasonable minimum gas limit for bridging. Since we always bridge as ERC-20
183
- // (wrapping native tokens), all tokens need sufficient gas for an ERC-20 transfer.
184
- if (map.minGas < MESSENGER_ERC20_MIN_GAS_LIMIT) {
185
- revert JBSucker_BelowMinGas({minGas: map.minGas, minGasLimit: MESSENGER_ERC20_MIN_GAS_LIMIT});
186
- }
187
- }
188
- }
@@ -1,96 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.28;
3
-
4
- // External packages (alphabetized).
5
- import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
6
- import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
7
- import {IJBTokens} from "@bananapus/core-v6/src/interfaces/IJBTokens.sol";
8
-
9
- // Local: interfaces (alphabetized).
10
- import {IJBCeloSuckerDeployer} from "../interfaces/IJBCeloSuckerDeployer.sol";
11
- import {IOPMessenger} from "../interfaces/IOPMessenger.sol";
12
- import {IOPStandardBridge} from "../interfaces/IOPStandardBridge.sol";
13
- import {IWrappedNativeToken} from "../interfaces/IWrappedNativeToken.sol";
14
-
15
- // Local: deployers.
16
- import {JBOptimismSuckerDeployer} from "./JBOptimismSuckerDeployer.sol";
17
-
18
- /// @notice An `IJBSuckerDeployer` implementation to deploy `JBCeloSucker` contracts.
19
- /// @dev Extends the OP deployer with a `wrappedNative` address for chains where ETH is an ERC-20.
20
- contract JBCeloSuckerDeployer is JBOptimismSuckerDeployer, IJBCeloSuckerDeployer {
21
- //*********************************************************************//
22
- // ---------------------- public stored properties ------------------- //
23
- //*********************************************************************//
24
-
25
- /// @notice The ERC-20 wrapper for the chain's native token on the local chain.
26
- IWrappedNativeToken public override wrappedNative;
27
-
28
- //*********************************************************************//
29
- // ---------------------------- constructor -------------------------- //
30
- //*********************************************************************//
31
-
32
- /// @param directory The directory of terminals and controllers for projects.
33
- /// @param permissions The permissions contract for the deployer.
34
- /// @param tokens The contract that manages token minting and burning.
35
- /// @param configurator The address of the configurator.
36
- /// @param trustedForwarder The trusted forwarder for ERC-2771 meta-transactions.
37
- constructor(
38
- IJBDirectory directory,
39
- IJBPermissions permissions,
40
- IJBTokens tokens,
41
- address configurator,
42
- address trustedForwarder
43
- )
44
- JBOptimismSuckerDeployer(directory, permissions, tokens, configurator, trustedForwarder)
45
- {}
46
-
47
- //*********************************************************************//
48
- // ------------------------ internal views --------------------------- //
49
- //*********************************************************************//
50
-
51
- /// @notice Check if the layer specific configuration is set or not. Used as a sanity check.
52
- /// @return A flag indicating whether the layer specific configuration has been set.
53
- function _layerSpecificConfigurationIsSet() internal view override returns (bool) {
54
- return
55
- address(opMessenger) != address(0) && address(opBridge) != address(0)
56
- && address(wrappedNative) != address(0);
57
- }
58
-
59
- //*********************************************************************//
60
- // --------------------- external transactions ----------------------- //
61
- //*********************************************************************//
62
-
63
- /// @notice Handles layer specific configuration including the wrapped native token.
64
- /// @param messenger The OPMessenger on this layer.
65
- /// @param bridge The OPStandardBridge on this layer.
66
- /// @param _wrappedNative The ERC-20 wrapper for the chain's native token on this layer.
67
- function setChainSpecificConstants(
68
- IOPMessenger messenger,
69
- IOPStandardBridge bridge,
70
- IWrappedNativeToken _wrappedNative
71
- )
72
- external
73
- {
74
- // Make sure the layer specific configuration has not already been set.
75
- if (_layerSpecificConfigurationIsSet()) {
76
- revert JBSuckerDeployer_AlreadyConfigured({
77
- singleton: address(singleton), layerSpecificConfigurationIsSet: true
78
- });
79
- }
80
-
81
- // Make sure only the configurator can call this function.
82
- if (_msgSender() != LAYER_SPECIFIC_CONFIGURATOR) {
83
- revert JBSuckerDeployer_Unauthorized({caller: _msgSender(), expected: LAYER_SPECIFIC_CONFIGURATOR});
84
- }
85
-
86
- // Configure these layer specific properties.
87
- opMessenger = messenger;
88
- opBridge = bridge;
89
- wrappedNative = _wrappedNative;
90
-
91
- // Make sure the layer specific configuration is properly configured.
92
- if (!_layerSpecificConfigurationIsSet()) {
93
- revert JBSuckerDeployer_InvalidLayerSpecificConfiguration({configurator: LAYER_SPECIFIC_CONFIGURATOR});
94
- }
95
- }
96
- }
@@ -1,12 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.0;
3
-
4
- /// @notice Immutable conversion rate for one received root batch, keyed by nonce.
5
- /// @dev Each batch stores its total leaf and local amounts. Individual claims compute their scaled amount as
6
- /// `claimLeafAmount * localTotal / leafTotal` — no mutable state changes.
7
- /// @custom:member leafTotal Total leaf-denomination (source chain) amount for this batch.
8
- /// @custom:member localTotal Total local-denomination (after swap) amount for this batch.
9
- struct JBConversionRate {
10
- uint256 leafTotal;
11
- uint256 localTotal;
12
- }
@@ -1,12 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.0;
3
-
4
- /// @notice Bridge tokens from a failed inbound swap, stored for later retry via `retrySwap`.
5
- /// @custom:member bridgeToken The bridge token received from CCIP.
6
- /// @custom:member bridgeAmount Amount of bridge tokens to swap.
7
- /// @custom:member leafTotal Original leaf-denomination total (for conversion rate).
8
- struct JBPendingSwap {
9
- address bridgeToken;
10
- uint256 bridgeAmount;
11
- uint256 leafTotal;
12
- }