@bananapus/suckers-v6 0.0.31 → 0.0.32

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.
Files changed (96) hide show
  1. package/README.md +2 -2
  2. package/foundry.lock +1 -7
  3. package/foundry.toml +1 -2
  4. package/package.json +24 -13
  5. package/references/operations.md +1 -1
  6. package/references/runtime.md +1 -1
  7. package/script/Deploy.s.sol +9 -0
  8. package/src/JBArbitrumSucker.sol +3 -1
  9. package/src/JBBaseSucker.sol +3 -1
  10. package/src/JBCCIPSucker.sol +16 -9
  11. package/src/JBCeloSucker.sol +6 -4
  12. package/src/JBOptimismSucker.sol +4 -2
  13. package/src/JBSucker.sol +180 -42
  14. package/src/JBSuckerRegistry.sol +94 -70
  15. package/src/JBSwapCCIPSucker.sol +43 -58
  16. package/src/deployers/JBSuckerDeployer.sol +5 -3
  17. package/src/interfaces/IJBPeerChainAdjustedAccounts.sol +21 -0
  18. package/src/interfaces/IJBSuckerDeployer.sol +3 -2
  19. package/src/interfaces/IJBSuckerExtended.sol +56 -0
  20. package/src/libraries/JBSuckerLib.sol +148 -73
  21. package/src/libraries/JBSwapLib.sol +4 -0
  22. package/src/libraries/JBSwapPoolLib.sol +214 -56
  23. package/src/structs/JBMessageRoot.sol +3 -2
  24. package/src/structs/JBSuckerDeployerConfig.sol +3 -0
  25. package/ADMINISTRATION.md +0 -26
  26. package/ARCHITECTURE.md +0 -34
  27. package/AUDIT_INSTRUCTIONS.md +0 -33
  28. package/RISKS.md +0 -161
  29. package/SKILLS.md +0 -25
  30. package/STYLE_GUIDE.md +0 -610
  31. package/USER_JOURNEYS.md +0 -50
  32. package/slither-ci.config.json +0 -10
  33. package/test/AdversarialSuckerFork.t.sol +0 -449
  34. package/test/ForkArbitrum.t.sol +0 -404
  35. package/test/ForkCelo.t.sol +0 -387
  36. package/test/ForkClaimMainnet.t.sol +0 -924
  37. package/test/ForkMainnet.t.sol +0 -521
  38. package/test/ForkOPStack.t.sol +0 -358
  39. package/test/ForkSwap.t.sol +0 -445
  40. package/test/ForkSwapMainnet.t.sol +0 -441
  41. package/test/InteropCompat.t.sol +0 -705
  42. package/test/MultiSuckerFork.t.sol +0 -529
  43. package/test/SuckerAttacks.t.sol +0 -540
  44. package/test/SuckerCrossChainAdversarial.t.sol +0 -745
  45. package/test/SuckerDeepAttacks.t.sol +0 -1740
  46. package/test/SuckerRegressions.t.sol +0 -366
  47. package/test/TestAuditGaps.sol +0 -1073
  48. package/test/audit/ArbitrumL2ToRemoteFeeDoS.t.sol +0 -137
  49. package/test/audit/CCIPLegacyFormatCompatibility.t.sol +0 -85
  50. package/test/audit/CCIPWrappedNativeMisunwrap.t.sol +0 -196
  51. package/test/audit/DeprecatedRemovalUndercount.t.sol +0 -141
  52. package/test/audit/DeprecatedSuckerAggregateViews.t.sol +0 -247
  53. package/test/audit/DeprecatedSuckerDestination.t.sol +0 -177
  54. package/test/audit/DeprecationBoundaryAndMapToken.t.sol +0 -352
  55. package/test/audit/FeeLocking.t.sol +0 -328
  56. package/test/audit/FreshRound.t.sol +0 -383
  57. package/test/audit/MapTokensEnableOnlyValueStuck.t.sol +0 -84
  58. package/test/audit/PeerDeterminism.t.sol +0 -174
  59. package/test/audit/PeerSnapshotDesync.t.sol +0 -162
  60. package/test/audit/PeerTopologyAuthBreak.t.sol +0 -112
  61. package/test/audit/RegistryPeerAuthBreak.t.sol +0 -198
  62. package/test/audit/RegistryPeerMismatch.t.sol +0 -112
  63. package/test/audit/RegistryStaleDeprecatedMaxSurplus.t.sol +0 -127
  64. package/test/audit/RegistryStaleMaxAggregation.t.sol +0 -88
  65. package/test/audit/StaleNonceMetadataOverwrite.t.sol +0 -318
  66. package/test/audit/SwapBatchRateMixing.t.sol +0 -139
  67. package/test/audit/SwapQueueOrder.t.sol +0 -186
  68. package/test/audit/SwapZeroAmountBatchGap.t.sol +0 -203
  69. package/test/audit/SwapZeroLocalTotalUnbackedClaim.t.sol +0 -179
  70. package/test/audit/ToRemoteFeeFallback.t.sol +0 -140
  71. package/test/audit/ToRemoteFeeIrrecoverable.t.sol +0 -253
  72. package/test/audit/TransientClaimContext.t.sol +0 -258
  73. package/test/audit/TrustedForwarderSpoof.t.sol +0 -121
  74. package/test/audit/TrustedForwarderSpoofCCIP.t.sol +0 -121
  75. package/test/audit/ZeroOutputRetryClaim.t.sol +0 -162
  76. package/test/audit/ZeroOutputSwapPending.t.sol +0 -218
  77. package/test/fork/OptimismSuckerFork.t.sol +0 -459
  78. package/test/helpers/SuckerForkHelpers.sol +0 -126
  79. package/test/mocks/ERC20Mock.sol +0 -37
  80. package/test/mocks/MockMessenger.sol +0 -43
  81. package/test/regression/MapTokensDust.t.sol +0 -237
  82. package/test/unit/arb.t.sol +0 -28
  83. package/test/unit/ccip_native_interop.t.sol +0 -737
  84. package/test/unit/ccip_refund.t.sol +0 -245
  85. package/test/unit/deployer.t.sol +0 -739
  86. package/test/unit/emergency.t.sol +0 -323
  87. package/test/unit/fee_fallback.t.sol +0 -259
  88. package/test/unit/invariants.t.sol +0 -480
  89. package/test/unit/merkle.t.sol +0 -232
  90. package/test/unit/merkle_equivalence.t.sol +0 -121
  91. package/test/unit/multi_chain_evolution.t.sol +0 -605
  92. package/test/unit/peer_chain_state.t.sol +0 -618
  93. package/test/unit/pool_discovery.t.sol +0 -366
  94. package/test/unit/registry.t.sol +0 -25
  95. package/test/unit/relay_beneficiary.t.sol +0 -141
  96. package/test/unit/swap_ccip.t.sol +0 -577
package/README.md CHANGED
@@ -72,8 +72,8 @@ That means every bridge path has two trust surfaces:
72
72
  1. `test/unit/registry.t.sol`
73
73
  2. `test/unit/multi_chain_evolution.t.sol`
74
74
  3. `test/ForkClaimMainnet.t.sol`
75
- 4. `test/audit/codex-PeerSnapshotDesync.t.sol`
76
- 5. `test/audit/codex-ToRemoteFeeIrrecoverable.t.sol`
75
+ 4. `test/audit/PeerSnapshotDesync.t.sol`
76
+ 5. `test/audit/ToRemoteFeeIrrecoverable.t.sol`
77
77
 
78
78
  ## Install
79
79
 
package/foundry.lock CHANGED
@@ -1,11 +1,5 @@
1
1
  {
2
2
  "lib/forge-std": {
3
3
  "rev": "83c5d212a01f8950727da4095cdfe2654baccb5b"
4
- },
5
- "lib/sphinx": {
6
- "branch": {
7
- "name": "v0.23.0",
8
- "rev": "5fb24a825f46bd6ae0b5359fe0da1d2346126b09"
9
- }
10
4
  }
11
- }
5
+ }
package/foundry.toml CHANGED
@@ -14,8 +14,7 @@ depth = 100
14
14
  fail_on_revert = false
15
15
 
16
16
  [lint]
17
- exclude_lints = ["pascal-case-struct", "mixed-case-variable"]
18
- lint_on_build = false
17
+ exclude_lints = ["mixed-case-variable", "pascal-case-struct"]
19
18
 
20
19
  [fmt]
21
20
  number_underscore = "thousands"
package/package.json CHANGED
@@ -1,11 +1,22 @@
1
1
  {
2
2
  "name": "@bananapus/suckers-v6",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/Bananapus/nana-suckers-v6"
8
8
  },
9
+ "files": [
10
+ "CHANGELOG.md",
11
+ "foundry.lock",
12
+ "foundry.toml",
13
+ "references/",
14
+ "remappings.txt",
15
+ "script/Deploy.s.sol",
16
+ "script/helpers/",
17
+ "sphinx.lock",
18
+ "src/"
19
+ ],
9
20
  "engines": {
10
21
  "node": ">=20.0.0"
11
22
  },
@@ -18,19 +29,19 @@
18
29
  "analyze": "slither . --config-file slither-ci.config.json"
19
30
  },
20
31
  "dependencies": {
21
- "@arbitrum/nitro-contracts": "^1.2.1",
22
- "@bananapus/core-v6": "^0.0.36",
23
- "@bananapus/permission-ids-v6": "^0.0.19",
24
- "@chainlink/contracts-ccip": "^1.6.0",
25
- "@chainlink/local": "github:smartcontractkit/chainlink-local#v0.2.7",
26
- "@openzeppelin/contracts": "^5.6.1",
27
- "@prb/math": "^4.1.0",
28
- "@uniswap/v3-core": "github:Uniswap/v3-core#0.8",
29
- "@uniswap/v3-periphery": "github:Uniswap/v3-periphery#0.8",
30
- "@uniswap/v4-core": "^1.0.2",
31
- "solady": "^0.1.26"
32
+ "@arbitrum/nitro-contracts": "3.2.0",
33
+ "@bananapus/core-v6": "0.0.39",
34
+ "@bananapus/permission-ids-v6": "0.0.22",
35
+ "@chainlink/contracts-ccip": "1.6.4",
36
+ "@chainlink/local": "0.2.7",
37
+ "@openzeppelin/contracts": "5.6.1",
38
+ "@prb/math": "4.1.1",
39
+ "@uniswap/v3-core": "github:Uniswap/v3-core#6562c52e8f75f0c10f9deaf44861847585fc8129",
40
+ "@uniswap/v3-periphery": "github:Uniswap/v3-periphery#b325bb0905d922ae61fcc7df85ee802e8df5e96c",
41
+ "@uniswap/v4-core": "1.0.2",
42
+ "solady": "0.1.26"
32
43
  },
33
44
  "devDependencies": {
34
- "@sphinx-labs/plugins": "^0.33.2"
45
+ "@sphinx-labs/plugins": "0.33.3"
35
46
  }
36
47
  }
@@ -25,4 +25,4 @@
25
25
 
26
26
  - [`test/SuckerAttacks.t.sol`](../test/SuckerAttacks.t.sol), [`test/SuckerDeepAttacks.t.sol`](../test/SuckerDeepAttacks.t.sol), and [`test/TestAuditGaps.sol`](../test/TestAuditGaps.sol) for security-sensitive assumptions.
27
27
  - [`test/InteropCompat.t.sol`](../test/InteropCompat.t.sol) when the problem is deployment wiring rather than runtime logic.
28
- - [`test/unit/invariants.t.sol`](../test/unit/invariants.t.sol), [`test/unit/peer_chain_state.t.sol`](../test/unit/peer_chain_state.t.sol), and [`test/audit/codex-PeerSnapshotDesync.t.sol`](../test/audit/codex-PeerSnapshotDesync.t.sol) when shared accounting or snapshot boundaries are in doubt.
28
+ - [`test/unit/invariants.t.sol`](../test/unit/invariants.t.sol), [`test/unit/peer_chain_state.t.sol`](../test/unit/peer_chain_state.t.sol), and [`test/audit/PeerSnapshotDesync.t.sol`](../test/audit/PeerSnapshotDesync.t.sol) when shared accounting or snapshot boundaries are in doubt.
@@ -27,4 +27,4 @@
27
27
  - [`test/ForkMainnet.t.sol`](../test/ForkMainnet.t.sol), [`test/ForkArbitrum.t.sol`](../test/ForkArbitrum.t.sol), [`test/ForkCelo.t.sol`](../test/ForkCelo.t.sol), and [`test/ForkOPStack.t.sol`](../test/ForkOPStack.t.sol) for real transport assumptions.
28
28
  - [`test/ForkSwap.t.sol`](../test/ForkSwap.t.sol), [`test/ForkClaimMainnet.t.sol`](../test/ForkClaimMainnet.t.sol), and [`test/SuckerRegressions.t.sol`](../test/SuckerRegressions.t.sol) for pinned cross-chain edge cases.
29
29
  - [`test/unit/invariants.t.sol`](../test/unit/invariants.t.sol), [`test/unit/peer_chain_state.t.sol`](../test/unit/peer_chain_state.t.sol), and [`test/unit/registry.t.sol`](../test/unit/registry.t.sol) for shared-accounting invariants.
30
- - [`test/SuckerAttacks.t.sol`](../test/SuckerAttacks.t.sol), [`test/SuckerDeepAttacks.t.sol`](../test/SuckerDeepAttacks.t.sol), [`test/audit/codex-PeerSnapshotDesync.t.sol`](../test/audit/codex-PeerSnapshotDesync.t.sol), and [`test/audit/codex-PeerDeterminism.t.sol`](../test/audit/codex-PeerDeterminism.t.sol) when the bug could involve base logic, registry behavior, or a specific bridge implementation.
30
+ - [`test/SuckerAttacks.t.sol`](../test/SuckerAttacks.t.sol), [`test/SuckerDeepAttacks.t.sol`](../test/SuckerDeepAttacks.t.sol), [`test/audit/PeerSnapshotDesync.t.sol`](../test/audit/PeerSnapshotDesync.t.sol), and [`test/audit/PeerDeterminism.t.sol`](../test/audit/PeerDeterminism.t.sol) when the bug could involve base logic, registry behavior, or a specific bridge implementation.
@@ -224,6 +224,7 @@ contract DeployScript is Script, Sphinx {
224
224
  deployer: _opDeployer,
225
225
  directory: core.directory,
226
226
  permissions: core.permissions,
227
+ prices: address(core.prices),
227
228
  tokens: core.tokens,
228
229
  feeProjectId: 1,
229
230
  registry: REGISTRY,
@@ -275,6 +276,7 @@ contract DeployScript is Script, Sphinx {
275
276
  deployer: _opDeployer,
276
277
  directory: core.directory,
277
278
  permissions: core.permissions,
279
+ prices: address(core.prices),
278
280
  tokens: core.tokens,
279
281
  feeProjectId: 1,
280
282
  registry: REGISTRY,
@@ -357,6 +359,7 @@ contract DeployScript is Script, Sphinx {
357
359
  deployer: _baseDeployer,
358
360
  directory: core.directory,
359
361
  permissions: core.permissions,
362
+ prices: address(core.prices),
360
363
  tokens: core.tokens,
361
364
  feeProjectId: 1,
362
365
  registry: REGISTRY,
@@ -408,6 +411,7 @@ contract DeployScript is Script, Sphinx {
408
411
  deployer: _baseDeployer,
409
412
  directory: core.directory,
410
413
  permissions: core.permissions,
414
+ prices: address(core.prices),
411
415
  tokens: core.tokens,
412
416
  feeProjectId: 1,
413
417
  registry: REGISTRY,
@@ -486,6 +490,7 @@ contract DeployScript is Script, Sphinx {
486
490
  deployer: _arbDeployer,
487
491
  directory: core.directory,
488
492
  permissions: core.permissions,
493
+ prices: address(core.prices),
489
494
  tokens: core.tokens,
490
495
  feeProjectId: 1,
491
496
  registry: REGISTRY,
@@ -540,6 +545,7 @@ contract DeployScript is Script, Sphinx {
540
545
  deployer: _arbDeployer,
541
546
  directory: core.directory,
542
547
  permissions: core.permissions,
548
+ prices: address(core.prices),
543
549
  tokens: core.tokens,
544
550
  feeProjectId: 1,
545
551
  registry: REGISTRY,
@@ -715,6 +721,7 @@ contract DeployScript is Script, Sphinx {
715
721
  salt: salt,
716
722
  directory: core.directory,
717
723
  permissions: core.permissions,
724
+ prices: address(core.prices),
718
725
  tokens: core.tokens,
719
726
  configurator: safeAddress(),
720
727
  trustedForwarder: TRUSTED_FORWARDER,
@@ -731,6 +738,7 @@ contract DeployScript is Script, Sphinx {
731
738
  bytes32 salt,
732
739
  IJBDirectory directory,
733
740
  IJBPermissions permissions,
741
+ address prices,
734
742
  IJBTokens tokens,
735
743
  address configurator,
736
744
  address trustedForwarder,
@@ -786,6 +794,7 @@ contract DeployScript is Script, Sphinx {
786
794
  directory: directory,
787
795
  tokens: tokens,
788
796
  permissions: permissions,
797
+ prices: prices,
789
798
  feeProjectId: 1,
790
799
  registry: REGISTRY,
791
800
  trustedForwarder: trustedForwarder
@@ -53,17 +53,19 @@ contract JBArbitrumSucker is JBSucker, IJBArbitrumSucker {
53
53
 
54
54
  /// @param directory A contract storing directories of terminals and controllers for each project.
55
55
  /// @param permissions A contract storing permissions.
56
+ /// @param prices The price oracle used to convert peer-chain balances and surplus.
56
57
  /// @param tokens A contract that manages token minting and burning.
57
58
  constructor(
58
59
  JBArbitrumSuckerDeployer deployer,
59
60
  IJBDirectory directory,
60
61
  IJBPermissions permissions,
62
+ address prices,
61
63
  IJBTokens tokens,
62
64
  uint256 feeProjectId,
63
65
  IJBSuckerRegistry registry,
64
66
  address trustedForwarder
65
67
  )
66
- JBSucker(directory, permissions, tokens, feeProjectId, registry, trustedForwarder)
68
+ JBSucker(directory, permissions, prices, tokens, feeProjectId, registry, trustedForwarder)
67
69
  {
68
70
  GATEWAYROUTER = JBArbitrumSuckerDeployer(deployer).arbGatewayRouter();
69
71
  ARBINBOX = JBArbitrumSuckerDeployer(deployer).arbInbox();
@@ -18,17 +18,19 @@ contract JBBaseSucker is JBOptimismSucker {
18
18
  /// @param deployer A contract that deploys the clones for this contracts.
19
19
  /// @param directory A contract storing directories of terminals and controllers for each project.
20
20
  /// @param permissions A contract storing permissions.
21
+ /// @param prices The price oracle used to convert peer-chain balances and surplus.
21
22
  /// @param tokens A contract that manages token minting and burning.
22
23
  constructor(
23
24
  JBOptimismSuckerDeployer deployer,
24
25
  IJBDirectory directory,
25
26
  IJBPermissions permissions,
27
+ address prices,
26
28
  IJBTokens tokens,
27
29
  uint256 feeProjectId,
28
30
  IJBSuckerRegistry registry,
29
31
  address trustedForwarder
30
32
  )
31
- JBOptimismSucker(deployer, directory, permissions, tokens, feeProjectId, registry, trustedForwarder)
33
+ JBOptimismSucker(deployer, directory, permissions, prices, tokens, feeProjectId, registry, trustedForwarder)
32
34
  {}
33
35
 
34
36
  //*********************************************************************//
@@ -42,10 +42,10 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
42
42
  //*********************************************************************//
43
43
 
44
44
  /// @notice Emitted when a transport payment refund fails after a successful CCIP send.
45
- /// @dev The refunded ETH is permanently stuck in this contract there is no recovery function.
46
- /// This is an accepted tradeoff to avoid reverting after CCIP has committed the bridge message.
45
+ /// @dev The refunded ETH is retained as account-scoped credit so the CCIP send does not revert after
46
+ /// committing the bridge message.
47
47
  /// @param recipient The address that was supposed to receive the refund.
48
- /// @param amount The amount of the failed refund (permanently stuck in this contract).
48
+ /// @param amount The amount of the failed refund.
49
49
  event TransportPaymentRefundFailed(address indexed recipient, uint256 amount);
50
50
 
51
51
  //*********************************************************************//
@@ -74,21 +74,23 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
74
74
 
75
75
  /// @param deployer A contract that deploys the clones for this contract.
76
76
  /// @param directory A contract storing directories of terminals and controllers for each project.
77
- /// @param tokens A contract that manages token minting and burning.
78
77
  /// @param permissions A contract storing permissions.
78
+ /// @param prices The price oracle used to convert peer-chain balances and surplus.
79
+ /// @param tokens A contract that manages token minting and burning.
79
80
  /// @param feeProjectId The ID of the project that receives fees.
80
81
  /// @param registry The sucker registry that tracks deployed suckers.
81
82
  /// @param trustedForwarder The trusted forwarder for ERC-2771 meta-transactions.
82
83
  constructor(
83
84
  JBCCIPSuckerDeployer deployer,
84
85
  IJBDirectory directory,
85
- IJBTokens tokens,
86
86
  IJBPermissions permissions,
87
+ address prices,
88
+ IJBTokens tokens,
87
89
  uint256 feeProjectId,
88
90
  IJBSuckerRegistry registry,
89
91
  address trustedForwarder
90
92
  )
91
- JBSucker(directory, permissions, tokens, feeProjectId, registry, trustedForwarder)
93
+ JBSucker(directory, permissions, prices, tokens, feeProjectId, registry, trustedForwarder)
92
94
  {
93
95
  // Read the remote chain ID from the deployer.
94
96
  REMOTE_CHAIN_ID = IJBCCIPSuckerDeployer(deployer).ccipRemoteChainId();
@@ -248,8 +250,13 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
248
250
  refundRecipient: _msgSender()
249
251
  });
250
252
 
251
- // Emit an event if the excess transport payment refund failed.
252
- if (refundFailed) emit TransportPaymentRefundFailed(_msgSender(), refundAmount);
253
+ // Retain failed refunds as caller credit instead of leaving them project-addable or stranded.
254
+ if (refundFailed) {
255
+ // Refund accounting is isolated per caller; reentry cannot increase the retained credit.
256
+ // slither-disable-next-line reentrancy-benign
257
+ _retainTransportPaymentRefund({account: _msgSender(), amount: refundAmount});
258
+ emit TransportPaymentRefundFailed({recipient: _msgSender(), amount: refundAmount});
259
+ }
253
260
  }
254
261
 
255
262
  //*********************************************************************//
@@ -282,7 +289,7 @@ contract JBCCIPSucker is JBSucker, IAny2EVMMessageReceiver {
282
289
  // funds. CCIP wraps native tokens to WETH before bridging (see `_sendRootOverAMB`), so ALL tokens —
283
290
  // including native — need sufficient gas for an ERC-20 transfer on the remote chain.
284
291
  if (map.minGas < MESSENGER_ERC20_MIN_GAS_LIMIT) {
285
- revert JBSucker_BelowMinGas(map.minGas, MESSENGER_ERC20_MIN_GAS_LIMIT);
292
+ revert JBSucker_BelowMinGas({minGas: map.minGas, minGasLimit: MESSENGER_ERC20_MIN_GAS_LIMIT});
286
293
  }
287
294
  }
288
295
  }
@@ -37,17 +37,19 @@ contract JBCeloSucker is JBOptimismSucker {
37
37
  /// @param deployer A contract that deploys the clones for this contracts.
38
38
  /// @param directory A contract storing directories of terminals and controllers for each project.
39
39
  /// @param permissions A contract storing permissions.
40
+ /// @param prices The price oracle used to convert peer-chain balances and surplus.
40
41
  /// @param tokens A contract that manages token minting and burning.
41
42
  constructor(
42
43
  JBCeloSuckerDeployer deployer,
43
44
  IJBDirectory directory,
44
45
  IJBPermissions permissions,
46
+ address prices,
45
47
  IJBTokens tokens,
46
48
  uint256 feeProjectId,
47
49
  IJBSuckerRegistry registry,
48
50
  address trustedForwarder
49
51
  )
50
- JBOptimismSucker(deployer, directory, permissions, tokens, feeProjectId, registry, trustedForwarder)
52
+ JBOptimismSucker(deployer, directory, permissions, prices, tokens, feeProjectId, registry, trustedForwarder)
51
53
  {
52
54
  // Fetch the wrapped native token by doing a callback to the deployer contract.
53
55
  WRAPPED_NATIVE = JBCeloSuckerDeployer(deployer).wrappedNative();
@@ -82,7 +84,7 @@ contract JBCeloSucker is JBOptimismSucker {
82
84
  // Check addable amount against WETH balance before unwrapping.
83
85
  uint256 addableAmount = amountToAddToBalanceOf(token);
84
86
  if (amount > addableAmount) {
85
- revert JBSucker_InsufficientBalance(amount, addableAmount);
87
+ revert JBSucker_InsufficientBalance({amount: amount, balance: addableAmount});
86
88
  }
87
89
 
88
90
  // Unwrap WETH → native ETH.
@@ -95,7 +97,7 @@ contract JBCeloSucker is JBOptimismSucker {
95
97
  DIRECTORY.primaryTerminalOf({projectId: cachedProjectId, token: JBConstants.NATIVE_TOKEN});
96
98
 
97
99
  if (address(terminal) == address(0)) {
98
- revert JBSucker_NoTerminalForToken(cachedProjectId, JBConstants.NATIVE_TOKEN);
100
+ revert JBSucker_NoTerminalForToken({projectId: cachedProjectId, token: JBConstants.NATIVE_TOKEN});
99
101
  }
100
102
 
101
103
  // Add native ETH to the project's balance.
@@ -186,7 +188,7 @@ contract JBCeloSucker is JBOptimismSucker {
186
188
  // Enforce a reasonable minimum gas limit for bridging. Since we always bridge as ERC-20
187
189
  // (wrapping native ETH to WETH), all tokens need sufficient gas for an ERC-20 transfer.
188
190
  if (map.minGas < MESSENGER_ERC20_MIN_GAS_LIMIT) {
189
- revert JBSucker_BelowMinGas(map.minGas, MESSENGER_ERC20_MIN_GAS_LIMIT);
191
+ revert JBSucker_BelowMinGas({minGas: map.minGas, minGasLimit: MESSENGER_ERC20_MIN_GAS_LIMIT});
190
192
  }
191
193
  }
192
194
  }
@@ -35,18 +35,20 @@ contract JBOptimismSucker is JBSucker, IJBOptimismSucker {
35
35
 
36
36
  /// @param deployer A contract that deploys the clones for this contracts.
37
37
  /// @param directory A contract storing directories of terminals and controllers for each project.
38
- /// @param tokens A contract that manages token minting and burning.
39
38
  /// @param permissions A contract storing permissions.
39
+ /// @param prices The price oracle used to convert peer-chain balances and surplus.
40
+ /// @param tokens A contract that manages token minting and burning.
40
41
  constructor(
41
42
  JBOptimismSuckerDeployer deployer,
42
43
  IJBDirectory directory,
43
44
  IJBPermissions permissions,
45
+ address prices,
44
46
  IJBTokens tokens,
45
47
  uint256 feeProjectId,
46
48
  IJBSuckerRegistry registry,
47
49
  address trustedForwarder
48
50
  )
49
- JBSucker(directory, permissions, tokens, feeProjectId, registry, trustedForwarder)
51
+ JBSucker(directory, permissions, prices, tokens, feeProjectId, registry, trustedForwarder)
50
52
  {
51
53
  // Fetch the messenger and bridge by doing a callback to the deployer contract.
52
54
  OPBRIDGE = JBOptimismSuckerDeployer(deployer).opBridge();