@bananapus/suckers-v6 0.0.16 → 0.0.18
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/AUDIT_INSTRUCTIONS.md +1 -1
- package/CHANGE_LOG.md +25 -2
- package/SKILLS.md +2 -0
- package/STYLE_GUIDE.md +2 -2
- package/foundry.toml +1 -1
- package/package.json +4 -3
- package/script/Deploy.s.sol +397 -216
- package/script/helpers/SuckerDeploymentLib.sol +5 -2
- package/src/JBArbitrumSucker.sol +2 -1
- package/src/JBBaseSucker.sol +1 -1
- package/src/JBCCIPSucker.sol +9 -3
- package/src/JBCeloSucker.sol +2 -1
- package/src/JBOptimismSucker.sol +2 -1
- package/src/JBSucker.sol +21 -15
- package/src/JBSuckerRegistry.sol +1 -1
- package/src/deployers/JBArbitrumSuckerDeployer.sol +1 -1
- package/src/deployers/JBBaseSuckerDeployer.sol +1 -1
- package/src/deployers/JBCCIPSuckerDeployer.sol +1 -1
- package/src/deployers/JBCeloSuckerDeployer.sol +1 -1
- package/src/deployers/JBOptimismSuckerDeployer.sol +1 -1
- package/src/deployers/JBSuckerDeployer.sol +1 -1
- package/src/interfaces/IJBCCIPSuckerDeployer.sol +0 -1
- package/src/interfaces/IJBSucker.sol +0 -2
- package/src/libraries/CCIPHelper.sol +1 -1
- package/src/structs/JBClaim.sol +1 -0
- package/src/structs/JBInboxTreeRoot.sol +1 -0
- package/src/structs/JBLeaf.sol +1 -0
- package/src/structs/JBMessageRoot.sol +1 -0
- package/src/structs/JBOutboxTree.sol +1 -0
- package/src/structs/JBRemoteToken.sol +1 -0
- package/src/structs/JBSuckerDeployerConfig.sol +1 -0
- package/src/structs/JBSuckersPair.sol +1 -0
- package/src/structs/JBTokenMapping.sol +1 -0
- package/src/utils/MerkleLib.sol +1 -1
- package/test/Fork.t.sol +6 -20
- package/test/ForkArbitrum.t.sol +3 -1
- package/test/ForkCelo.t.sol +6 -1
- package/test/ForkClaim.t.sol +6 -16
- package/test/ForkMainnet.t.sol +4 -2
- package/test/ForkOPStack.t.sol +3 -1
- package/test/InteropCompat.t.sol +12 -1
- package/test/SuckerAttacks.t.sol +4 -3
- package/test/SuckerDeepAttacks.t.sol +12 -1
- package/test/SuckerRegressions.t.sol +5 -3
- package/test/TestAuditGaps.sol +6 -5
- package/test/audit/ArbitrumL2ToRemoteFeeDoS.t.sol +9 -1
- package/test/audit/{CodexNemesisPoC.t.sol → DeprecatedSuckerDestination.t.sol} +12 -14
- package/test/audit/ToRemoteFeeFallback.t.sol +131 -0
- package/test/audit/TrustedForwarderSpoof.t.sol +109 -0
- package/test/audit/TrustedForwarderSpoofCCIP.t.sol +112 -0
- package/test/fork/OptimismSuckerFork.t.sol +4 -2
- package/test/mocks/ERC20Mock.sol +1 -0
- package/test/mocks/MockMessenger.sol +1 -0
- package/test/regression/MapTokensDust.t.sol +3 -1
- package/test/unit/arb.t.sol +1 -1
- package/test/unit/ccip_native_interop.t.sol +12 -2
- package/test/unit/ccip_refund.t.sol +4 -6
- package/test/unit/deployer.t.sol +17 -7
- package/test/unit/emergency.t.sol +6 -0
- package/test/unit/fee_fallback.t.sol +243 -0
- package/test/unit/invariants.t.sol +3 -1
- package/test/unit/merkle.t.sol +6 -0
- package/test/unit/multi_chain_evolution.t.sol +23 -2
- package/test/unit/registry.t.sol +3 -4
package/AUDIT_INSTRUCTIONS.md
CHANGED
|
@@ -373,7 +373,7 @@ The test suite covers core flows but these areas have limited or no coverage:
|
|
|
373
373
|
|
|
374
374
|
## Compiler and Version Info
|
|
375
375
|
|
|
376
|
-
- **Solidity**:
|
|
376
|
+
- **Solidity**: 0.8.28
|
|
377
377
|
- **EVM target**: Cancun
|
|
378
378
|
- **Optimizer**: 200 runs (via-IR is NOT enabled)
|
|
379
379
|
- **Dependencies**: OpenZeppelin 5.x, Arbitrum SDK, Chainlink CCIP, nana-core-v6
|
package/CHANGE_LOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nana-suckers-v6 Changelog (v5 -> v6)
|
|
2
2
|
|
|
3
|
-
This document describes all changes between `nana-suckers` (v5, Solidity 0.8.23) and `nana-suckers-v6` (v6, Solidity
|
|
3
|
+
This document describes all changes between `nana-suckers` (v5, Solidity 0.8.23) and `nana-suckers-v6` (v6, Solidity 0.8.28).
|
|
4
4
|
|
|
5
5
|
## Summary
|
|
6
6
|
|
|
@@ -188,6 +188,13 @@ In v5, `JBSucker.initialize()` used `msg.sender` to set the `deployer` field. In
|
|
|
188
188
|
|
|
189
189
|
## 3. Event Changes
|
|
190
190
|
|
|
191
|
+
### 3.0 Indexer Notes
|
|
192
|
+
|
|
193
|
+
This repo requires the largest schema change for subgraphs:
|
|
194
|
+
- any entity keyed by beneficiary, remote address, or remote token must now support raw `bytes32`;
|
|
195
|
+
- do not assume every remote identifier can be rendered as an EVM checksum address;
|
|
196
|
+
- separate transport-fee accounting from bridged-token accounting, since `toRemoteFee` replaced `minBridgeAmount`.
|
|
197
|
+
|
|
191
198
|
### 3.1 New Events
|
|
192
199
|
|
|
193
200
|
See section 2.3 above.
|
|
@@ -366,7 +373,7 @@ See section 2.4 above.
|
|
|
366
373
|
|
|
367
374
|
### 7.9 Solidity Version
|
|
368
375
|
|
|
369
|
-
All contracts upgraded from `pragma solidity 0.8.23` to `pragma solidity
|
|
376
|
+
All contracts upgraded from `pragma solidity 0.8.23` to `pragma solidity 0.8.28`.
|
|
370
377
|
|
|
371
378
|
### 7.10 Named Arguments
|
|
372
379
|
|
|
@@ -440,3 +447,19 @@ Throughout the codebase, function calls were updated to use named argument synta
|
|
|
440
447
|
| `ARBChains` | `ARBChains` | Identical |
|
|
441
448
|
| `CCIPHelper` | `CCIPHelper` | Bare `revert("Unsupported chain")` replaced with typed `CCIPHelper_UnsupportedChain` error. |
|
|
442
449
|
| `MerkleLib` | `MerkleLib` | Identical |
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## 9. Post-Audit Fixes
|
|
454
|
+
|
|
455
|
+
### 9.1 Deploy Script Resumability (NEW-L-1)
|
|
456
|
+
|
|
457
|
+
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.
|
|
458
|
+
|
|
459
|
+
**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.
|
|
460
|
+
|
|
461
|
+
### 9.2 Fee Fallback DoS on Zero-Cost Bridges
|
|
462
|
+
|
|
463
|
+
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`.
|
|
464
|
+
|
|
465
|
+
**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.
|
package/SKILLS.md
CHANGED
|
@@ -158,6 +158,8 @@ Cross-chain token and fund bridging for Juicebox V6 projects, using merkle trees
|
|
|
158
158
|
- `toRemote` fee payment is best-effort: if the fee project has no native token terminal or `terminal.pay()` reverts, `toRemote` proceeds without collecting the fee. The caller still receives project tokens from the fee payment when it succeeds.
|
|
159
159
|
- `JBCCIPSucker` transport payment refund uses a low-level `call` that does NOT revert on failure. If the refund fails (e.g., caller is a non-payable contract), the excess ETH is permanently stuck. The `TransportPaymentRefundFailed` event provides observability.
|
|
160
160
|
- The sucker has an unrestricted `receive()` function -- it must accept ETH from bridges, WETH unwrapping, and terminal cash-outs. Excess ETH increases `amountToAddToBalanceOf` for the project (not a double-spend risk).
|
|
161
|
+
- `fromRemote()` validates the peer using `msg.sender`, not `_msgSender()`. Using `_msgSender()` would allow a trusted ERC-2771 forwarder to spoof the bridge peer address. Never use a meta-tx forwarder as a relay for `fromRemote` calls.
|
|
162
|
+
- `ccipReceive()` validates the CCIP router using `msg.sender`, not `_msgSender()`, for the same reason. A trusted forwarder could append the router address via the ERC-2771 calldata suffix and fully control the `Any2EVMMessage` struct.
|
|
161
163
|
|
|
162
164
|
### CRITICAL: NATIVE_TOKEN Mismatch on Non-ETH Chains
|
|
163
165
|
|
package/STYLE_GUIDE.md
CHANGED
|
@@ -21,7 +21,7 @@ One contract/interface/struct/enum per file. Name the file after the type it con
|
|
|
21
21
|
|
|
22
22
|
```solidity
|
|
23
23
|
// Contracts — pin to exact version
|
|
24
|
-
pragma solidity
|
|
24
|
+
pragma solidity 0.8.28;
|
|
25
25
|
|
|
26
26
|
// Interfaces, structs, enums — caret for forward compatibility
|
|
27
27
|
pragma solidity ^0.8.0;
|
|
@@ -328,7 +328,7 @@ Standard config across all repos:
|
|
|
328
328
|
|
|
329
329
|
```toml
|
|
330
330
|
[profile.default]
|
|
331
|
-
solc = '0.8.
|
|
331
|
+
solc = '0.8.28'
|
|
332
332
|
evm_version = 'cancun'
|
|
333
333
|
optimizer_runs = 200
|
|
334
334
|
libs = ["node_modules", "lib"]
|
package/foundry.toml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bananapus/suckers-v6",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@arbitrum/nitro-contracts": "^1.2.1",
|
|
22
|
-
"@bananapus/
|
|
23
|
-
"@bananapus/
|
|
22
|
+
"@bananapus/address-registry-v6": "^0.0.16",
|
|
23
|
+
"@bananapus/core-v6": "^0.0.28",
|
|
24
|
+
"@bananapus/permission-ids-v6": "^0.0.14",
|
|
24
25
|
"@chainlink/contracts-ccip": "^1.5.0",
|
|
25
26
|
"@chainlink/local": "github:smartcontractkit/chainlink-local",
|
|
26
27
|
"@openzeppelin/contracts": "^5.6.1",
|