@bananapus/suckers-v6 0.0.20 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ADMINISTRATION.md +36 -5
- package/ARCHITECTURE.md +42 -103
- package/AUDIT_INSTRUCTIONS.md +116 -386
- package/CHANGELOG.md +72 -0
- package/README.md +87 -415
- package/RISKS.md +22 -5
- package/SKILLS.md +29 -250
- package/STYLE_GUIDE.md +58 -21
- package/USER_JOURNEYS.md +47 -311
- package/package.json +2 -3
- package/references/operations.md +25 -0
- package/references/runtime.md +28 -0
- package/script/Deploy.s.sol +7 -7
- package/src/JBCeloSucker.sol +4 -2
- package/src/JBSucker.sol +4 -4
- package/src/JBSuckerRegistry.sol +5 -1
- package/src/interfaces/IJBSuckerRegistry.sol +2 -0
- package/src/libraries/ARBAddresses.sol +1 -1
- package/src/libraries/ARBChains.sol +1 -1
- package/test/audit/codex-ToRemoteFeeIrrecoverable.t.sol +238 -0
- package/CHANGE_LOG.md +0 -484
package/CHANGE_LOG.md
DELETED
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
# nana-suckers-v6 Changelog (v5 -> v6)
|
|
2
|
-
|
|
3
|
-
This document describes all changes between `nana-suckers` (v5, Solidity 0.8.23) and `nana-suckers-v6` (v6, Solidity 0.8.28).
|
|
4
|
-
|
|
5
|
-
## Summary
|
|
6
|
-
|
|
7
|
-
The dominant theme of this release is **cross-VM preparation for Solana/SVM** — addresses throughout the sucker architecture are widened from `address` (20 bytes) to `bytes32` (32 bytes) to support non-EVM chains.
|
|
8
|
-
|
|
9
|
-
- **`address` → `bytes32` throughout**: All cross-chain identifiers (peer addresses, beneficiaries, remote tokens) widened to `bytes32` for Solana/SVM compatibility. `uint128` amount caps added for SVM compatibility.
|
|
10
|
-
- **Message versioning**: New `version` field in `JBMessageRoot` prevents v5/v6 message incompatibility. v6 messages use `MESSAGE_VERSION = 1`.
|
|
11
|
-
- **Anti-spam redesigned**: Per-token `minBridgeAmount` replaced by a global `toRemoteFee` (max 0.001 ETH) paid to the fee project on every `toRemote()` call.
|
|
12
|
-
- **`MANUAL` add-to-balance mode removed**: Balance is always added atomically during `claim()`, simplifying the sucker lifecycle.
|
|
13
|
-
- **New Celo support**: `JBCeloSucker` handles Celo's non-ETH native gas token via WETH wrapping.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 1. Breaking Changes
|
|
18
|
-
|
|
19
|
-
### 1.1 Cross-VM Address Representation (`address` -> `bytes32`)
|
|
20
|
-
|
|
21
|
-
The most pervasive breaking change in v6 is the systematic replacement of `address` types with `bytes32` for all cross-chain identifiers. This prepares the sucker architecture for non-EVM chains (e.g., Solana/SVM) where addresses are 32 bytes. Two new internal helpers (`_toAddress` and `_toBytes32`) convert between the two representations at EVM bridge API boundaries.
|
|
22
|
-
|
|
23
|
-
#### IJBSucker
|
|
24
|
-
|
|
25
|
-
| Change | v5 | v6 |
|
|
26
|
-
|--------|----|----|
|
|
27
|
-
| `peer()` return type | `returns (address)` | `returns (bytes32)` |
|
|
28
|
-
| `prepare()` beneficiary param | `address beneficiary` | `bytes32 beneficiary` |
|
|
29
|
-
| `Claimed` event `beneficiary` | `address beneficiary` | `bytes32 beneficiary` |
|
|
30
|
-
| `Claimed` event `autoAddedToBalance` | `bool autoAddedToBalance` | _(removed)_ |
|
|
31
|
-
| `InsertToOutboxTree` event `beneficiary` | `address indexed beneficiary` | `bytes32 indexed beneficiary` |
|
|
32
|
-
|
|
33
|
-
All callers of `peer()` and `prepare()` must update to use `bytes32`. For EVM-to-EVM usage, addresses are left-padded to 32 bytes via `_toBytes32(address)`.
|
|
34
|
-
|
|
35
|
-
> **Cross-repo impact**: `nana-omnichain-deployers-v6` and `nana-fee-project-deployer-v6` both updated `JBTokenMapping.remoteToken` from `address` to `bytes32`. `nana-permission-ids-v6` split `SUCKER_SAFETY` into two permissions (`SUCKER_SAFETY` + `SET_SUCKER_DEPRECATION`) to match the v6 separation.
|
|
36
|
-
|
|
37
|
-
### 1.2 Struct Field Type Changes
|
|
38
|
-
|
|
39
|
-
| Struct | Field | v5 Type | v6 Type |
|
|
40
|
-
|--------|-------|---------|---------|
|
|
41
|
-
| `JBLeaf` | `beneficiary` | `address` | `bytes32` |
|
|
42
|
-
| `JBMessageRoot` | `token` | `address` | `bytes32` |
|
|
43
|
-
| `JBMessageRoot` | (new field) `version` | N/A | `uint8` (inserted as first field) |
|
|
44
|
-
| `JBRemoteToken` | `addr` | `address` | `bytes32` |
|
|
45
|
-
| `JBRemoteToken` | `minBridgeAmount` | `uint256` | _(removed)_ |
|
|
46
|
-
| `JBSuckersPair` | `remote` | `address` | `bytes32` |
|
|
47
|
-
| `JBTokenMapping` | `remoteToken` | `address` | `bytes32` |
|
|
48
|
-
| `JBTokenMapping` | `minBridgeAmount` | `uint256` | _(removed)_ |
|
|
49
|
-
|
|
50
|
-
These are ABI-breaking changes. All off-chain infrastructure (indexers, relayers, frontends) must update to use `bytes32` for these fields.
|
|
51
|
-
|
|
52
|
-
### 1.3 Message Versioning (New Field in `JBMessageRoot`)
|
|
53
|
-
|
|
54
|
-
`JBMessageRoot` gained a `version` field (`uint8`). The v6 `fromRemote()` function validates `root.version == MESSAGE_VERSION` (which is `1`) and reverts with `JBSucker_InvalidMessageVersion` if it does not match. This means v5 messages (which have no version field) are incompatible with v6 suckers.
|
|
55
|
-
|
|
56
|
-
### 1.4 `setDeprecation` Permission Change
|
|
57
|
-
|
|
58
|
-
| Change | v5 | v6 |
|
|
59
|
-
|--------|----|----|
|
|
60
|
-
| `setDeprecation` required permission | `JBPermissionIds.SUCKER_SAFETY` | `JBPermissionIds.SET_SUCKER_DEPRECATION` |
|
|
61
|
-
|
|
62
|
-
`enableEmergencyHatchFor` continues to use `JBPermissionIds.SUCKER_SAFETY` in both versions.
|
|
63
|
-
|
|
64
|
-
### 1.5 Removed Interfaces
|
|
65
|
-
|
|
66
|
-
| File | Notes |
|
|
67
|
-
|------|-------|
|
|
68
|
-
| `IJBSuckerDeployerFeeless.sol` | Removed entirely. The feeless allowance sucker pattern was removed. |
|
|
69
|
-
|
|
70
|
-
### 1.6 Removed Contracts
|
|
71
|
-
|
|
72
|
-
| File | Notes |
|
|
73
|
-
|------|-------|
|
|
74
|
-
| `extensions/JBAllowanceSucker.sol` | Abstract contract for feeless cash outs via `useAllowanceFeeless`. Removed along with `IJBSuckerDeployerFeeless`. |
|
|
75
|
-
|
|
76
|
-
### 1.7 IJBSuckerDeployer Errors Moved
|
|
77
|
-
|
|
78
|
-
In v5, deployer errors were declared in `IJBSuckerDeployer` (the interface). In v6, they are declared in `JBSuckerDeployer` (the abstract contract). The errors themselves are identical:
|
|
79
|
-
- `JBSuckerDeployer_AlreadyConfigured()`
|
|
80
|
-
- `JBSuckerDeployer_DeployerIsNotConfigured()`
|
|
81
|
-
- `JBSuckerDeployer_InvalidLayerSpecificConfiguration()`
|
|
82
|
-
- `JBSuckerDeployer_LayerSpecificNotConfigured()`
|
|
83
|
-
- `JBSuckerDeployer_Unauthorized(address caller, address expected)`
|
|
84
|
-
- `JBSuckerDeployer_ZeroConfiguratorAddress()`
|
|
85
|
-
|
|
86
|
-
### 1.8 IJBSuckerRegistry `deploySuckersFor` Parameter Change
|
|
87
|
-
|
|
88
|
-
| Change | v5 | v6 |
|
|
89
|
-
|--------|----|----|
|
|
90
|
-
| `deploySuckersFor` configurations param | `JBSuckerDeployerConfig[] memory configurations` | `JBSuckerDeployerConfig[] calldata configurations` |
|
|
91
|
-
|
|
92
|
-
Changed from `memory` to `calldata` for gas efficiency.
|
|
93
|
-
|
|
94
|
-
### 1.9 Anti-Spam Mechanism: `minBridgeAmount` Replaced by `toRemoteFee`
|
|
95
|
-
|
|
96
|
-
The v5 per-token `minBridgeAmount` anti-spam mechanism has been replaced by a global `toRemoteFee` in v6. This is a fundamental design change:
|
|
97
|
-
|
|
98
|
-
| Aspect | v5 | v6 |
|
|
99
|
-
|--------|----|----|
|
|
100
|
-
| Mechanism | Per-token minimum bridge threshold (`minBridgeAmount` in `JBRemoteToken`/`JBTokenMapping`) | Global ETH fee paid on every `toRemote()` call |
|
|
101
|
-
| Configuration | Set per-token during `mapTokens()` | Centralized in `JBSuckerRegistry`, admin-adjustable via `setToRemoteFee()` |
|
|
102
|
-
| Check | `_outboxOf[token].balance < remoteToken.minBridgeAmount` reverts with `JBSucker_QueueInsufficientSize` | `msg.value < toRemoteFee` reverts with `JBSucker_InsufficientMsgValue` |
|
|
103
|
-
| Fee destination | N/A (no fee, just a threshold) | Paid into `FEE_PROJECT_ID` via `terminal.pay()`. Caller receives fee project tokens. |
|
|
104
|
-
| Cap | None | `MAX_TO_REMOTE_FEE = 0.001 ether` |
|
|
105
|
-
|
|
106
|
-
The `JBSucker` constructor gained two new parameters: `feeProjectId` (the project that receives the fee, typically project ID 1) and `registry` (typed as `IJBSuckerRegistry`, which manages the global `toRemoteFee`). These replace the `addToBalanceMode` parameter. See section 1.10 for the `addToBalanceMode` removal.
|
|
107
|
-
|
|
108
|
-
### 1.10 `MANUAL` `AddToBalanceMode` Removed
|
|
109
|
-
|
|
110
|
-
The `MANUAL` option of `JBAddToBalanceMode` has been removed entirely. In v5, suckers could be deployed with either `MANUAL` or `ON_CLAIM` mode. In v6, balance is always added atomically during `claim()` (the `ON_CLAIM` behavior). This simplifies the sucker lifecycle.
|
|
111
|
-
|
|
112
|
-
| Removed in v6 | Description |
|
|
113
|
-
|----------------|-------------|
|
|
114
|
-
| `JBAddToBalanceMode` enum | Removed. Only had `MANUAL` and `ON_CLAIM`. |
|
|
115
|
-
| `ADD_TO_BALANCE_MODE` immutable | Removed from `JBSucker` and `IJBSucker`. |
|
|
116
|
-
| `addOutstandingAmountToBalance(address token)` | Public function removed from `IJBSucker` and `JBSucker`. Was only usable in `MANUAL` mode. |
|
|
117
|
-
| `JBSucker_ManualNotAllowed` error | Removed (was thrown when calling `addOutstandingAmountToBalance` in non-MANUAL mode). |
|
|
118
|
-
|
|
119
|
-
Note: `amountToAddToBalanceOf(address token)` is still present in v6 -- it is used internally by the always-on-claim flow.
|
|
120
|
-
|
|
121
|
-
### 1.11 JBSucker Constructor Change
|
|
122
|
-
|
|
123
|
-
| Parameter | v5 | v6 |
|
|
124
|
-
|-----------|----|----|
|
|
125
|
-
| `addToBalanceMode` | `JBAddToBalanceMode addToBalanceMode` | _(removed)_ |
|
|
126
|
-
| `feeProjectId` | _(not present)_ | `uint256 feeProjectId` |
|
|
127
|
-
| `registry` | _(not present)_ | `IJBSuckerRegistry registry` |
|
|
128
|
-
| `trusted_forwarder` naming | `address trusted_forwarder` | `address trustedForwarder` (camelCase) |
|
|
129
|
-
|
|
130
|
-
All subclass constructors (`JBOptimismSucker`, `JBArbitrumSucker`, `JBCCIPSucker`, `JBBaseSucker`, `JBCeloSucker`) are updated accordingly.
|
|
131
|
-
|
|
132
|
-
### 1.12 `initialize()` ERC2771 Fix
|
|
133
|
-
|
|
134
|
-
In v5, `JBSucker.initialize()` used `msg.sender` to set the `deployer` field. In v6, this was corrected to `_msgSender()` for ERC2771 meta-transaction compatibility. This is a behavioral fix: when called through a trusted forwarder, v5 would incorrectly record the forwarder address as the deployer instead of the actual sender.
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## 2. New Features
|
|
139
|
-
|
|
140
|
-
### 2.1 New Contracts
|
|
141
|
-
|
|
142
|
-
| Contract | Description |
|
|
143
|
-
|----------|-------------|
|
|
144
|
-
| `JBCeloSucker` | OP Stack sucker for Celo, which uses CELO as its native gas token (not ETH). Wraps native ETH to WETH before bridging as ERC-20. Overrides `_sendRootOverAMB` to always bridge as ERC-20 and never attach ETH as `msg.value` on the messenger. Overrides `_addToBalance` to unwrap WETH back to native ETH. Overrides `_validateTokenMapping` to allow `NATIVE_TOKEN` to map to any remote token. Supports chain IDs: Ethereum (1) <-> Celo (42220). |
|
|
145
|
-
| `JBCeloSuckerDeployer` | Deployer for `JBCeloSucker`. Extends `JBOptimismSuckerDeployer` with a `wrappedNative` address. Has its own `setChainSpecificConstants` that accepts an additional `IWrappedNativeToken` parameter. |
|
|
146
|
-
|
|
147
|
-
### 2.2 New Interfaces
|
|
148
|
-
|
|
149
|
-
| Interface | Description |
|
|
150
|
-
|-----------|-------------|
|
|
151
|
-
| `IJBCeloSuckerDeployer` | Interface for the Celo sucker deployer. Extends `IJBOpSuckerDeployer` with `wrappedNative()` view and `setChainSpecificConstants(IOPMessenger, IOPStandardBridge, IWrappedNativeToken)`. |
|
|
152
|
-
|
|
153
|
-
### 2.3 New Events
|
|
154
|
-
|
|
155
|
-
| Contract | Event | Description |
|
|
156
|
-
|----------|-------|-------------|
|
|
157
|
-
| `IJBSucker` | `StaleRootRejected(address indexed token, uint64 receivedNonce, uint64 currentNonce)` | Emitted when a received inbox root is rejected because its nonce is stale (not greater than the current nonce). Aids off-chain monitoring of out-of-order or duplicate message deliveries. |
|
|
158
|
-
| `IJBSuckerExtended` | `EmergencyExit(address indexed beneficiary, address indexed token, uint256 terminalTokenAmount, uint256 projectTokenCount, address caller)` | Emitted when a beneficiary exits through the emergency hatch. v5 had no event for emergency exits. |
|
|
159
|
-
| `JBCCIPSucker` | `TransportPaymentRefundFailed(address indexed recipient, uint256 amount)` | Emitted when a CCIP transport payment refund fails after a successful `ccipSend`. Replaces the v5 `JBCCIPSucker_FailedToRefundFee` revert to avoid reverting after the bridge message is committed. |
|
|
160
|
-
| `IJBSuckerRegistry` | `ToRemoteFeeChanged(uint256 oldFee, uint256 newFee, address caller)` | Emitted when the registry owner changes the global `toRemoteFee`. New in v6 (no v5 equivalent). |
|
|
161
|
-
|
|
162
|
-
### 2.4 New Errors
|
|
163
|
-
|
|
164
|
-
| Contract | Error | Description |
|
|
165
|
-
|----------|-------|-------------|
|
|
166
|
-
| `JBSucker` | `JBSucker_AmountExceedsUint128(uint256 amount)` | Thrown when `terminalTokenAmount` or `projectTokenCount` exceeds `uint128` in `_insertIntoTree`. Guards against overflow for SVM/Solana compatibility. |
|
|
167
|
-
| `JBSucker` | `JBSucker_InvalidMessageVersion(uint8 received, uint8 expected)` | Thrown in `fromRemote` when the message version does not match `MESSAGE_VERSION`. Prevents processing incompatible messages. |
|
|
168
|
-
| `JBSucker` | `JBSucker_NothingToSend()` | Thrown in `toRemote()` when the outbox has zero balance and no unsent claims. Prevents unnecessary bridge calls. |
|
|
169
|
-
| `JBSucker` | `JBSucker_IndexOutOfRange(uint256 index)` | Thrown in `_validate()` and `_validateForEmergencyExit()` when the leaf index exceeds the tree depth (`>= 2^32`). Prevents wasted gas on impossible proofs. |
|
|
170
|
-
| `CCIPHelper` | `CCIPHelper_UnsupportedChain(uint256 chainId)` | Replaces bare `revert("Unsupported chain")` strings with a typed error. |
|
|
171
|
-
| `JBSuckerRegistry` | `JBSuckerRegistry_FeeExceedsMax(uint256 fee, uint256 max)` | Thrown when `setToRemoteFee` is called with a fee exceeding `MAX_TO_REMOTE_FEE`. |
|
|
172
|
-
|
|
173
|
-
### 2.5 New Constants
|
|
174
|
-
|
|
175
|
-
| Contract | Constant | Description |
|
|
176
|
-
|----------|----------|-------------|
|
|
177
|
-
| `JBSucker` | `uint8 public constant MESSAGE_VERSION = 1` | The message format version. Used to reject incompatible messages from remote chains. |
|
|
178
|
-
| `JBSuckerRegistry` | `uint256 public constant MAX_TO_REMOTE_FEE = 0.001 ether` | The maximum ETH fee the registry owner can set via `setToRemoteFee()`. |
|
|
179
|
-
|
|
180
|
-
### 2.6 New Internal Helpers
|
|
181
|
-
|
|
182
|
-
| Contract | Function | Description |
|
|
183
|
-
|----------|----------|-------------|
|
|
184
|
-
| `JBSucker` | `_toAddress(bytes32) -> address` | Converts a `bytes32` remote address to a local EVM address (lower 20 bytes). |
|
|
185
|
-
| `JBSucker` | `_toBytes32(address) -> bytes32` | Converts an EVM address to a `bytes32` remote address (left-padded with zeros). |
|
|
186
|
-
| `JBArbitrumSucker` | `_createRetryableTicket(...)` | Helper to create the retryable ticket, extracted from `_toL2` to avoid stack-too-deep errors. |
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## 3. Event Changes
|
|
191
|
-
|
|
192
|
-
### 3.0 Indexer Notes
|
|
193
|
-
|
|
194
|
-
This repo requires the largest schema change for subgraphs:
|
|
195
|
-
- any entity keyed by beneficiary, remote address, or remote token must now support raw `bytes32`;
|
|
196
|
-
- do not assume every remote identifier can be rendered as an EVM checksum address;
|
|
197
|
-
- separate transport-fee accounting from bridged-token accounting, since `toRemoteFee` replaced `minBridgeAmount`.
|
|
198
|
-
|
|
199
|
-
### 3.1 New Events
|
|
200
|
-
|
|
201
|
-
See section 2.3 above.
|
|
202
|
-
|
|
203
|
-
### 3.2 Modified Events
|
|
204
|
-
|
|
205
|
-
| Contract | Event | Change |
|
|
206
|
-
|----------|-------|--------|
|
|
207
|
-
| `IJBSucker` | `Claimed` | `beneficiary` field changed from `address` to `bytes32`. `bool autoAddedToBalance` parameter removed (the `MANUAL` add-to-balance mode was removed in v6, so balance is always added on claim). |
|
|
208
|
-
| `IJBSucker` | `InsertToOutboxTree` | `beneficiary` indexed field changed from `address indexed` to `bytes32 indexed`. |
|
|
209
|
-
|
|
210
|
-
### 3.3 Unchanged Events
|
|
211
|
-
|
|
212
|
-
`NewInboxTreeRoot`, `RootToRemote`, `EmergencyHatchOpened`, `DeprecationTimeUpdated`, `SuckerDeployedFor`, `SuckerDeployerAllowed`, `SuckerDeployerRemoved`, `SuckerDeprecated`, and `CCIPConstantsSet` are identical between v5 and v6.
|
|
213
|
-
|
|
214
|
-
### 3.4 All Interfaces Gained NatSpec
|
|
215
|
-
|
|
216
|
-
Every interface file in v6 has comprehensive NatSpec documentation added to all functions, events, errors, and return values. This is a documentation-only change that does not affect the ABI.
|
|
217
|
-
|
|
218
|
-
---
|
|
219
|
-
|
|
220
|
-
## 4. Error Changes
|
|
221
|
-
|
|
222
|
-
### 4.1 New Errors
|
|
223
|
-
|
|
224
|
-
See section 2.4 above.
|
|
225
|
-
|
|
226
|
-
### 4.2 Modified Error Parameters (Type Changes)
|
|
227
|
-
|
|
228
|
-
| Contract | v5 | v6 |
|
|
229
|
-
|----------|----|----|
|
|
230
|
-
| `JBSucker` | `JBSucker_NotPeer(address caller)` | `JBSucker_NotPeer(bytes32 caller)` |
|
|
231
|
-
| `JBSucker` | `JBSucker_InvalidNativeRemoteAddress(address remoteToken)` | `JBSucker_InvalidNativeRemoteAddress(bytes32 remoteToken)` |
|
|
232
|
-
| `JBSucker` | `JBSucker_TokenAlreadyMapped(address localToken, address mappedTo)` | `JBSucker_TokenAlreadyMapped(address localToken, bytes32 mappedTo)` |
|
|
233
|
-
|
|
234
|
-
### 4.3 Removed Errors
|
|
235
|
-
|
|
236
|
-
| Contract | Error | Notes |
|
|
237
|
-
|----------|-------|-------|
|
|
238
|
-
| `JBArbitrumSucker` | `JBArbitrumSucker_ChainNotSupported(uint256 chainId)` | Error was declared but never used in v5. Removed. |
|
|
239
|
-
| `JBCCIPSucker` | `JBCCIPSucker_FailedToRefundFee()` | Replaced by `TransportPaymentRefundFailed` event. Refund failure no longer reverts. |
|
|
240
|
-
| `JBSucker` | `JBSucker_ManualNotAllowed(JBAddToBalanceMode mode)` | Removed along with `MANUAL` `AddToBalanceMode`. Balance is always added on claim in v6. |
|
|
241
|
-
| `JBSucker` | `JBSucker_QueueInsufficientSize(uint256 amount, uint256 minimumAmount)` | Removed. The per-token `minBridgeAmount` threshold was replaced by the global `toRemoteFee` mechanism. |
|
|
242
|
-
| `JBSuckerRegistry` | `JBSuckerRegistry_RulesetDoesNotAllowAddingSucker(uint256 projectId)` | Removed entirely (was declared but unused in v5). |
|
|
243
|
-
|
|
244
|
-
### 4.4 Moved Errors (Interface -> Contract)
|
|
245
|
-
|
|
246
|
-
| v5 Location | v6 Location | Errors |
|
|
247
|
-
|-------------|-------------|--------|
|
|
248
|
-
| `IJBSuckerDeployer` (interface) | `JBSuckerDeployer` (abstract contract) | `JBSuckerDeployer_AlreadyConfigured`, `JBSuckerDeployer_DeployerIsNotConfigured`, `JBSuckerDeployer_InvalidLayerSpecificConfiguration`, `JBSuckerDeployer_LayerSpecificNotConfigured`, `JBSuckerDeployer_Unauthorized`, `JBSuckerDeployer_ZeroConfiguratorAddress` |
|
|
249
|
-
|
|
250
|
-
### 4.5 Library Error Improvements
|
|
251
|
-
|
|
252
|
-
| Library | v5 | v6 |
|
|
253
|
-
|---------|----|----|
|
|
254
|
-
| `CCIPHelper` | `revert("Unsupported chain")` (bare string revert) | `revert CCIPHelper_UnsupportedChain(chainId)` (typed error with chain ID) |
|
|
255
|
-
|
|
256
|
-
---
|
|
257
|
-
|
|
258
|
-
## 5. Struct Changes
|
|
259
|
-
|
|
260
|
-
### 5.1 Modified Structs
|
|
261
|
-
|
|
262
|
-
| Struct | Field | v5 Type | v6 Type | Notes |
|
|
263
|
-
|--------|-------|---------|---------|-------|
|
|
264
|
-
| `JBLeaf` | `beneficiary` | `address` | `bytes32` | Cross-VM compatibility |
|
|
265
|
-
| `JBMessageRoot` | `token` | `address` | `bytes32` | Cross-VM compatibility |
|
|
266
|
-
| `JBMessageRoot` | `version` | _(not present)_ | `uint8` | New field for message versioning (first field) |
|
|
267
|
-
| `JBRemoteToken` | `addr` | `address` | `bytes32` | Cross-VM compatibility |
|
|
268
|
-
| `JBRemoteToken` | `minBridgeAmount` | `uint256` | _(removed)_ | Anti-spam moved to global `toRemoteFee` in `JBSuckerRegistry` |
|
|
269
|
-
| `JBSuckersPair` | `remote` | `address` | `bytes32` | Cross-VM compatibility |
|
|
270
|
-
| `JBTokenMapping` | `remoteToken` | `address` | `bytes32` | Cross-VM compatibility |
|
|
271
|
-
| `JBTokenMapping` | `minBridgeAmount` | `uint256` | _(removed)_ | Anti-spam moved to global `toRemoteFee` in `JBSuckerRegistry` |
|
|
272
|
-
|
|
273
|
-
### 5.2 Unchanged Structs
|
|
274
|
-
|
|
275
|
-
| Struct | Notes |
|
|
276
|
-
|--------|-------|
|
|
277
|
-
| `JBClaim` | Identical (but contains `JBLeaf`, which changed) |
|
|
278
|
-
| `JBInboxTreeRoot` | Identical |
|
|
279
|
-
| `JBOutboxTree` | Identical |
|
|
280
|
-
| `JBSuckerDeployerConfig` | Identical (but contains `JBTokenMapping`, which changed) |
|
|
281
|
-
|
|
282
|
-
---
|
|
283
|
-
|
|
284
|
-
## 6. Enum Changes
|
|
285
|
-
|
|
286
|
-
`JBLayer` and `JBSuckerState` are **identical** between v5 and v6. `JBAddToBalanceMode` has been removed — balance is now always added atomically during `claim()`.
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
## 7. Implementation Changes (Non-Interface)
|
|
291
|
-
|
|
292
|
-
### 7.1 JBSucker
|
|
293
|
-
|
|
294
|
-
| Change | Description |
|
|
295
|
-
|--------|-------------|
|
|
296
|
-
| **Message versioning** | `fromRemote()` now validates `root.version == MESSAGE_VERSION` and reverts with `JBSucker_InvalidMessageVersion` on mismatch. v5 had no version check. |
|
|
297
|
-
| **Stale root event** | `fromRemote()` emits `StaleRootRejected` in the else branch when a root is rejected due to a stale nonce. v5 silently ignored stale roots. |
|
|
298
|
-
| **Token field in `fromRemote`** | `fromRemote()` now converts `root.token` (bytes32) to a local address via `_toAddress()` for inbox lookup, since `JBMessageRoot.token` changed from `address` to `bytes32`. |
|
|
299
|
-
| **uint128 overflow guard** | `_insertIntoTree()` now checks that `terminalTokenAmount` and `projectTokenCount` do not exceed `uint128`, reverting with `JBSucker_AmountExceedsUint128`. Guards against overflow when bridging to SVM/Solana. |
|
|
300
|
-
| **Empty outbox guard** | `_sendRoot()` now returns early (no-op) if `outbox.tree.count == 0`, preventing an arithmetic underflow when computing `count - 1`. v5 did not have this guard. |
|
|
301
|
-
| **Emergency exit event** | `exitThroughEmergencyHatch()` now emits the `EmergencyExit` event. v5 had no event for emergency exits. |
|
|
302
|
-
| **`setDeprecation` permission** | Changed from `JBPermissionIds.SUCKER_SAFETY` to `JBPermissionIds.SET_SUCKER_DEPRECATION`. |
|
|
303
|
-
| **`_addToBalance` visibility** | Changed from `internal` to `internal virtual`, allowing subclasses (e.g., `JBCeloSucker`) to override. |
|
|
304
|
-
| **`peer()` return type** | Changed from `address` to `bytes32`. Default implementation returns `_toBytes32(address(this))`. |
|
|
305
|
-
| **`isMapped()` comparison** | Changed from `_remoteTokenFor[token].addr != address(0)` to `_remoteTokenFor[token].addr != bytes32(0)`. |
|
|
306
|
-
| **Private variable naming** | `localProjectId` renamed to `_localProjectId` (leading underscore convention). |
|
|
307
|
-
| **`mapTokens` dust refund** | `mapTokens()` now refunds the remainder from integer division of `msg.value` when disabling multiple tokens, preventing dust ETH from being stuck in the contract. |
|
|
308
|
-
| **`_handleClaim` beneficiary conversion** | Converts `bytes32` beneficiary to `address` via `_toAddress()` before minting project tokens. |
|
|
309
|
-
| **`_sendRoot` message construction** | Now includes `version: MESSAGE_VERSION` in the `JBMessageRoot` struct. |
|
|
310
|
-
| **`toRemoteFee` anti-spam** | `toRemote()` now charges a global ETH fee (read from `REGISTRY.toRemoteFee()`) paid into `FEE_PROJECT_ID` via `terminal.pay()`. Replaces the v5 per-token `minBridgeAmount` threshold check. Fee payment is best-effort (try-catch): if the terminal doesn't exist or the pay call reverts, the fee is returned as transport payment. |
|
|
311
|
-
| **New immutables** | `FEE_PROJECT_ID` (`uint256`) and `REGISTRY` (`IJBSuckerRegistry`) added. `REGISTRY` is typed as `IJBSuckerRegistry` (not a raw `address`), avoiding casts at usage sites. |
|
|
312
|
-
| **`MANUAL` mode removed** | `ADD_TO_BALANCE_MODE` immutable, `addOutstandingAmountToBalance()` function, and `JBSucker_ManualNotAllowed` error all removed. Balance is always added atomically during `claim()`. |
|
|
313
|
-
| **Constructor parameter changes** | `addToBalanceMode` parameter removed. `feeProjectId` and `registry` parameters added. `trusted_forwarder` renamed to `trustedForwarder`. |
|
|
314
|
-
| **`initialize()` ERC2771 fix** | `deployer = msg.sender` changed to `deployer = _msgSender()` for correct ERC2771 meta-transaction support. |
|
|
315
|
-
| **Named arguments** | Function calls throughout use named argument syntax (`{key: value}`) for improved readability. |
|
|
316
|
-
|
|
317
|
-
### 7.2 JBOptimismSucker
|
|
318
|
-
|
|
319
|
-
| Change | Description |
|
|
320
|
-
|--------|-------------|
|
|
321
|
-
| **`_isRemotePeer` comparison** | v5: `OPMESSENGER.xDomainMessageSender() == peer()` (address comparison). v6: `_toBytes32(OPMESSENGER.xDomainMessageSender()) == peer()` (bytes32 comparison). |
|
|
322
|
-
| **Bridge API calls** | `OPBRIDGE.bridgeERC20To` and `OPMESSENGER.sendMessage` now convert `bytes32` types to `address` at the OP Bridge API boundary via `_toAddress()`. |
|
|
323
|
-
| **`_sendRootOverAMB` visibility** | Changed from `internal override` to `internal virtual override`, allowing `JBCeloSucker` to override. |
|
|
324
|
-
|
|
325
|
-
### 7.3 JBArbitrumSucker
|
|
326
|
-
|
|
327
|
-
| Change | Description |
|
|
328
|
-
|--------|-------------|
|
|
329
|
-
| **`_isRemotePeer` comparison** | v5: compared directly with `peer()` (address). v6: converts `peer()` to address via `_toAddress()` before comparison with bridge contracts. |
|
|
330
|
-
| **Bridge API calls** | `IArbL2GatewayRouter.outboundTransfer`, `ArbSys.sendTxToL1`, and `IArbL1GatewayRouter.outboundTransferCustomRefund` now convert `bytes32` types to `address` via `_toAddress()`. |
|
|
331
|
-
| **Stack-too-deep refactor** | `_toL2` extracted `_createRetryableTicket` helper to avoid stack-too-deep. v5 inlined the `ARBINBOX.unsafeCreateRetryableTicket` call. |
|
|
332
|
-
| **Removed error** | `JBArbitrumSucker_ChainNotSupported` removed (was unused in v5). |
|
|
333
|
-
|
|
334
|
-
### 7.4 JBCCIPSucker
|
|
335
|
-
|
|
336
|
-
| Change | Description |
|
|
337
|
-
|--------|-------------|
|
|
338
|
-
| **Refund failure handling** | v5: reverted with `JBCCIPSucker_FailedToRefundFee()` on refund failure. v6: emits `TransportPaymentRefundFailed` event instead. This prevents reverting after `ccipSend` has already committed the bridge message, which would cause the transaction to roll back while the CCIP message is in-flight, potentially causing token loss. |
|
|
339
|
-
| **`ccipReceive` peer check** | v5: `revert JBSucker_NotPeer(_msgSender())` / `revert JBSucker_NotPeer(origin)`. v6: wraps in `_toBytes32()` to match the new `bytes32` error parameter. |
|
|
340
|
-
| **`ccipReceive` token comparison** | v5: `root.token == JBConstants.NATIVE_TOKEN`. v6: `root.token == _toBytes32(JBConstants.NATIVE_TOKEN)`, since `root.token` is now `bytes32`. |
|
|
341
|
-
| **CCIP message receiver** | v5: `abi.encode(peer())` (address). v6: `abi.encode(_toAddress(peer()))` (converts bytes32 back to address for CCIP EVM compatibility). |
|
|
342
|
-
| **`_validateTokenMapping`** | v6 enforces `minGas >= MESSENGER_ERC20_MIN_GAS_LIMIT` for ALL tokens (including native), since CCIP wraps native tokens to WETH. v5 exempted native tokens from the minGas check. |
|
|
343
|
-
| **Removed `CCIPHelper` import** | v6 no longer imports `CCIPHelper` in `JBCCIPSucker`. |
|
|
344
|
-
|
|
345
|
-
### 7.5 JBSuckerRegistry
|
|
346
|
-
|
|
347
|
-
| Change | Description |
|
|
348
|
-
|--------|-------------|
|
|
349
|
-
| **License** | Changed from `UNLICENSED` to `MIT`. |
|
|
350
|
-
| **Removed imports** | `IJBController`, `JBRuleset`, `JBRulesetMetadata` no longer imported. The v5 ruleset-based sucker restriction was removed. |
|
|
351
|
-
| **Removed error** | `JBSuckerRegistry_RulesetDoesNotAllowAddingSucker` removed. |
|
|
352
|
-
| **`suckerPairsOf`** | `sucker.peer()` now returns `bytes32`, directly assigned to `JBSuckersPair.remote` (which also changed to `bytes32`). |
|
|
353
|
-
| **`toRemoteFee` management** | New `toRemoteFee` storage variable (admin-adjustable ETH fee), `MAX_TO_REMOTE_FEE` constant (`0.001 ether`), `setToRemoteFee(uint256)` function (owner-only), `ToRemoteFeeChanged` event, and `JBSuckerRegistry_FeeExceedsMax` error. Defaults to `MAX_TO_REMOTE_FEE` on construction. |
|
|
354
|
-
|
|
355
|
-
### 7.6 JBSuckerDeployer
|
|
356
|
-
|
|
357
|
-
| Change | Description |
|
|
358
|
-
|--------|-------------|
|
|
359
|
-
| **Errors moved** | All deployer errors moved from `IJBSuckerDeployer` (interface) to `JBSuckerDeployer` (abstract contract). The interface is now error-free. |
|
|
360
|
-
| **Constructor parameter naming** | `trusted_forwarder` renamed to `trustedForwarder` (camelCase convention). |
|
|
361
|
-
|
|
362
|
-
### 7.7 JBOptimismSuckerDeployer
|
|
363
|
-
|
|
364
|
-
| Change | Description |
|
|
365
|
-
|--------|-------------|
|
|
366
|
-
| **`_layerSpecificConfigurationIsSet` operator** | v5: `address(opMessenger) != address(0) \|\| address(opBridge) != address(0)` (OR -- accepts partial config). v6: `address(opMessenger) != address(0) && address(opBridge) != address(0)` (AND -- rejects partial config). This ensures both messenger and bridge must be set, preventing misconfiguration. |
|
|
367
|
-
| **`_layerSpecificConfigurationIsSet` visibility** | Changed from `internal view override` to `internal view virtual override`, allowing `JBCeloSuckerDeployer` to override. |
|
|
368
|
-
|
|
369
|
-
### 7.8 CCIPHelper Library
|
|
370
|
-
|
|
371
|
-
| Change | Description |
|
|
372
|
-
|--------|-------------|
|
|
373
|
-
| **Typed error** | Bare `revert("Unsupported chain")` strings replaced with `revert CCIPHelper_UnsupportedChain(chainId)` in `routerOfChain`, `selectorOfChain`, and `wethOfChain`. |
|
|
374
|
-
|
|
375
|
-
### 7.9 Solidity Version
|
|
376
|
-
|
|
377
|
-
All contracts upgraded from `pragma solidity 0.8.23` to `pragma solidity 0.8.28`.
|
|
378
|
-
|
|
379
|
-
### 7.10 Named Arguments
|
|
380
|
-
|
|
381
|
-
Throughout the codebase, function calls were updated to use named argument syntax (e.g., `foo({bar: 1, baz: 2})`) for improved readability.
|
|
382
|
-
|
|
383
|
-
---
|
|
384
|
-
|
|
385
|
-
## 8. Migration Table
|
|
386
|
-
|
|
387
|
-
### Interfaces
|
|
388
|
-
|
|
389
|
-
| v5 | v6 | Notes |
|
|
390
|
-
|----|----|-------|
|
|
391
|
-
| `IJBSucker` | `IJBSucker` | `peer()` returns `bytes32`. `prepare()` takes `bytes32 beneficiary`. `Claimed`/`InsertToOutboxTree` events use `bytes32`. `Claimed` event `autoAddedToBalance` parameter removed. New `StaleRootRejected` event. New `JBSucker_NothingToSend` error. `ADD_TO_BALANCE_MODE()` and `addOutstandingAmountToBalance()` removed. NatSpec added. |
|
|
392
|
-
| `IJBSuckerExtended` | `IJBSuckerExtended` | New `EmergencyExit` event. NatSpec added. |
|
|
393
|
-
| `IJBSuckerRegistry` | `IJBSuckerRegistry` | `deploySuckersFor` configurations changed to `calldata`. New `toRemoteFee()`, `MAX_TO_REMOTE_FEE()`, `setToRemoteFee()`, `ToRemoteFeeChanged` event, `FeeExceedsMax` error. NatSpec added. |
|
|
394
|
-
| `IJBSuckerDeployer` | `IJBSuckerDeployer` | All errors removed from interface (moved to contract). NatSpec added. |
|
|
395
|
-
| `IJBSuckerDeployerFeeless` | (removed) | Feeless allowance sucker pattern removed. No replacement. |
|
|
396
|
-
| `IJBArbitrumSucker` | `IJBArbitrumSucker` | NatSpec added. No functional changes. |
|
|
397
|
-
| `IJBArbitrumSuckerDeployer` | `IJBArbitrumSuckerDeployer` | NatSpec added. No functional changes. |
|
|
398
|
-
| `IJBOptimismSucker` | `IJBOptimismSucker` | NatSpec added. No functional changes. |
|
|
399
|
-
| `IJBOpSuckerDeployer` | `IJBOpSuckerDeployer` | NatSpec added. No functional changes. |
|
|
400
|
-
| `IJBCCIPSuckerDeployer` | `IJBCCIPSuckerDeployer` | NatSpec added. No functional changes. |
|
|
401
|
-
| N/A | `IJBCeloSuckerDeployer` | New. Extends `IJBOpSuckerDeployer` with `wrappedNative()` and extended `setChainSpecificConstants`. |
|
|
402
|
-
| All other interfaces | Same name | NatSpec documentation added. No functional changes. |
|
|
403
|
-
|
|
404
|
-
### Contracts
|
|
405
|
-
|
|
406
|
-
| v5 | v6 | Notes |
|
|
407
|
-
|----|----|-------|
|
|
408
|
-
| `JBSucker` | `JBSucker` | `address` -> `bytes32` throughout, message versioning, uint128 guard, empty outbox guard, stale root event, emergency exit event, `setDeprecation` permission change, `mapTokens` dust refund, virtual `_addToBalance`. `minBridgeAmount` replaced by `toRemoteFee`. `MANUAL` mode removed. New `FEE_PROJECT_ID` + `REGISTRY` immutables. `initialize()` uses `_msgSender()`. |
|
|
409
|
-
| `JBOptimismSucker` | `JBOptimismSucker` | `_sendRootOverAMB` made `virtual`. Bridge calls use `_toAddress()`/`_toBytes32()`. |
|
|
410
|
-
| `JBBaseSucker` | `JBBaseSucker` | Explicit imports instead of wildcard. No functional changes. |
|
|
411
|
-
| `JBArbitrumSucker` | `JBArbitrumSucker` | Bridge calls use `_toAddress()`. `_createRetryableTicket` helper extracted. Removed unused `ChainNotSupported` error. |
|
|
412
|
-
| `JBCCIPSucker` | `JBCCIPSucker` | Refund failure emits event instead of reverting. `_validateTokenMapping` enforces minGas for native tokens. Bridge calls use `_toAddress()`/`_toBytes32()`. Removed `CCIPHelper` import. |
|
|
413
|
-
| N/A | `JBCeloSucker` | New. OP Stack sucker for Celo (custom gas token). Wraps ETH to WETH for bridging, unwraps on receipt. |
|
|
414
|
-
| `JBSuckerRegistry` | `JBSuckerRegistry` | Removed ruleset check and related imports/error. License changed to MIT. New `toRemoteFee` management (`setToRemoteFee`, `MAX_TO_REMOTE_FEE`, `ToRemoteFeeChanged` event). |
|
|
415
|
-
| `JBSuckerDeployer` | `JBSuckerDeployer` | Errors moved from interface to contract. Constructor param naming convention updated. |
|
|
416
|
-
| `JBOptimismSuckerDeployer` | `JBOptimismSuckerDeployer` | `_layerSpecificConfigurationIsSet` uses `&&` instead of `\|\|`. Made `virtual`. |
|
|
417
|
-
| N/A | `JBCeloSuckerDeployer` | New. Extends OP deployer with wrapped native token support. |
|
|
418
|
-
| `extensions/JBAllowanceSucker` | (removed) | Feeless allowance sucker pattern removed. |
|
|
419
|
-
| All deployers | Same name | Solidity version, named arguments, NatSpec. |
|
|
420
|
-
|
|
421
|
-
### Structs
|
|
422
|
-
|
|
423
|
-
| v5 | v6 | Notes |
|
|
424
|
-
|----|----|-------|
|
|
425
|
-
| `JBLeaf` | `JBLeaf` | `beneficiary`: `address` -> `bytes32` |
|
|
426
|
-
| `JBMessageRoot` | `JBMessageRoot` | `token`: `address` -> `bytes32`. New `version` field (`uint8`). |
|
|
427
|
-
| `JBRemoteToken` | `JBRemoteToken` | `addr`: `address` -> `bytes32`. `minBridgeAmount` removed. |
|
|
428
|
-
| `JBSuckersPair` | `JBSuckersPair` | `remote`: `address` -> `bytes32` |
|
|
429
|
-
| `JBTokenMapping` | `JBTokenMapping` | `remoteToken`: `address` -> `bytes32`. `minBridgeAmount` removed. |
|
|
430
|
-
| `JBClaim` | `JBClaim` | Unchanged (contains changed `JBLeaf`) |
|
|
431
|
-
| `JBInboxTreeRoot` | `JBInboxTreeRoot` | Identical |
|
|
432
|
-
| `JBOutboxTree` | `JBOutboxTree` | Identical |
|
|
433
|
-
| `JBSuckerDeployerConfig` | `JBSuckerDeployerConfig` | Unchanged (contains changed `JBTokenMapping`) |
|
|
434
|
-
|
|
435
|
-
### Enums
|
|
436
|
-
|
|
437
|
-
| v5 | v6 | Notes |
|
|
438
|
-
|----|----|-------|
|
|
439
|
-
| `JBAddToBalanceMode` | _(removed)_ | Balance always added on claim. |
|
|
440
|
-
| `JBLayer` | `JBLayer` | Identical |
|
|
441
|
-
| `JBSuckerState` | `JBSuckerState` | Identical |
|
|
442
|
-
|
|
443
|
-
### Libraries
|
|
444
|
-
|
|
445
|
-
| v5 | v6 | Notes |
|
|
446
|
-
|----|----|-------|
|
|
447
|
-
| `ARBAddresses` | `ARBAddresses` | Identical |
|
|
448
|
-
| `ARBChains` | `ARBChains` | Identical |
|
|
449
|
-
| `CCIPHelper` | `CCIPHelper` | Bare `revert("Unsupported chain")` replaced with typed `CCIPHelper_UnsupportedChain` error. |
|
|
450
|
-
| `MerkleLib` | `MerkleLib` | Identical |
|
|
451
|
-
|
|
452
|
-
---
|
|
453
|
-
|
|
454
|
-
## 9. Post-Audit Fixes
|
|
455
|
-
|
|
456
|
-
### 9.1 Deploy Script Resumability (NEW-L-1)
|
|
457
|
-
|
|
458
|
-
The `Deploy.s.sol` script's `_optimismSucker()`, `_baseSucker()`, `_arbitrumSucker()`, and `_deployCCIPSuckerWith()` functions previously returned early when the deployer contract existed at the CREATE2 address, without checking whether singleton configuration or registry allowlisting had completed. If a non-Sphinx deployment was interrupted after deployer creation but before `setChainSpecificConstants()`, `configureSingleton()`, or `allowSuckerDeployers()`, re-running the script would skip the incomplete deployer, leaving it unusable.
|
|
459
|
-
|
|
460
|
-
**Fix**: The early return now requires both `singleton != address(0)` and `REGISTRY.suckerDeployerIsAllowed(deployer)` to be true. If the deployer exists but is not fully configured, the script resumes from where it left off — skipping already-completed steps (deployer creation, chain-specific constants, singleton deployment) and executing only the missing ones. A new `_computeAddress()` helper was added to reuse the CREATE2 address computation logic.
|
|
461
|
-
|
|
462
|
-
### 9.2 Fee Fallback DoS on Zero-Cost Bridges
|
|
463
|
-
|
|
464
|
-
The `JBSucker.toRemote()` fee payment has a best-effort pattern: if the fee terminal is missing or the `pay()` call reverts, the transaction should proceed without the fee. Previously, the catch block and no-terminal branch reset `transportPayment = msg.value`, restoring the fee amount into the transport payment. This caused zero-cost bridges (OP, Base, Celo, Arbitrum L2->L1) to revert with `JBSucker_UnexpectedMsgValue` because they check `if (transportPayment != 0) revert`.
|
|
465
|
-
|
|
466
|
-
**Fix**: On fee payment failure, `transportPayment` is no longer overwritten. It stays at `msg.value - _toRemoteFee` (which is 0 when the caller sends exactly the fee amount). The fee ETH is retained by the sucker contract rather than being added back to the transport payment. This preserves bridge compatibility for all zero-cost bridge implementations.
|
|
467
|
-
|
|
468
|
-
### 9.3 Index Bounds Check in `_validate` and `_validateForEmergencyExit`
|
|
469
|
-
|
|
470
|
-
`_validate()` and `_validateForEmergencyExit()` did not check whether the leaf `index` exceeded the tree depth (`2^32 - 1`). While the merkle proof verification would still fail for out-of-range indices (since no valid proof exists), the missing check allowed unnecessary gas consumption and unclear revert messages.
|
|
471
|
-
|
|
472
|
-
**Fix**: Both functions now revert with `JBSucker_IndexOutOfRange(index)` if `index >= (1 << _TREE_DEPTH)`. This is a new custom error added to `JBSucker`.
|
|
473
|
-
|
|
474
|
-
### 9.4 Missing `wethOfChain` Entries for OP Sepolia and Base Sepolia
|
|
475
|
-
|
|
476
|
-
`CCIPHelper.wethOfChain()` did not have entries for `OP_SEP_ID` (Optimism Sepolia) or `BASE_SEP_ID` (Base Sepolia), causing CCIP sucker deployments on those testnets to revert with `CCIPHelper_UnsupportedChain`.
|
|
477
|
-
|
|
478
|
-
**Fix**: Added `OP_SEP_WETH` and `BASE_SEP_WETH` constants (`0x4200000000000000000000000000000000000006`) and corresponding branches in `wethOfChain()`.
|
|
479
|
-
|
|
480
|
-
### 9.5 NatSpec Fix for Salt Encoding
|
|
481
|
-
|
|
482
|
-
The NatSpec comment on `JBSucker.peer()` incorrectly described the deployer's salt computation as `keccak256(abi.encode(_msgSender(), salt))`. The actual code in `JBSuckerDeployer.createForSender()` uses `keccak256(abi.encodePacked(_msgSender(), salt))`.
|
|
483
|
-
|
|
484
|
-
**Fix**: Updated the NatSpec to say `abi.encodePacked` to match the implementation.
|