@bananapus/suckers-v6 0.0.49 → 0.0.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@bananapus/suckers-v6",
3
- "version": "0.0.49",
3
+ "version": "0.0.51",
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
9
  "files": [
10
- "CHANGELOG.md",
11
10
  "foundry.lock",
12
11
  "foundry.toml",
13
12
  "references/",
@@ -30,7 +29,7 @@
30
29
  },
31
30
  "dependencies": {
32
31
  "@arbitrum/nitro-contracts": "3.2.0",
33
- "@bananapus/core-v6": "^0.0.57",
32
+ "@bananapus/core-v6": "^0.0.59",
34
33
  "@bananapus/permission-ids-v6": "^0.0.26",
35
34
  "@chainlink/contracts-ccip": "1.6.4",
36
35
  "@chainlink/local": "0.2.7",
package/src/JBSucker.sol CHANGED
@@ -294,12 +294,15 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
294
294
  /// project tokens for the beneficiary, and deposits the terminal tokens into the project's local balance.
295
295
  /// @param claimData The terminal token, merkle tree leaf, and proof for the claim.
296
296
  function claim(JBClaim calldata claimData) public virtual override {
297
- // Attempt to validate the proof against the inbox tree for the terminal token.
297
+ // Attempt to validate the proof against the inbox tree for the terminal token. The leaf hash includes
298
+ // `claimData.leaf.metadata` so the proof is only valid for the exact (amount, beneficiary, metadata) tuple the
299
+ // origin committed to.
298
300
  _validate({
299
301
  projectTokenCount: claimData.leaf.projectTokenCount,
300
302
  terminalToken: claimData.token,
301
303
  terminalTokenAmount: claimData.leaf.terminalTokenAmount,
302
304
  beneficiary: claimData.leaf.beneficiary,
305
+ metadata: claimData.leaf.metadata,
303
306
  index: claimData.leaf.index,
304
307
  leaves: claimData.proof
305
308
  });
@@ -310,6 +313,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
310
313
  projectTokenCount: claimData.leaf.projectTokenCount,
311
314
  terminalTokenAmount: claimData.leaf.terminalTokenAmount,
312
315
  index: claimData.leaf.index,
316
+ metadata: claimData.leaf.metadata,
313
317
  caller: _msgSender()
314
318
  });
315
319
 
@@ -330,7 +334,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
330
334
  uint256 _projectId = projectId();
331
335
 
332
336
  _requirePermissionFrom({
333
- account: PROJECTS.ownerOf(_projectId), projectId: _projectId, permissionId: JBPermissionIds.SUCKER_SAFETY
337
+ account: _ownerOf(_projectId), projectId: _projectId, permissionId: JBPermissionIds.SUCKER_SAFETY
334
338
  });
335
339
 
336
340
  // Enable the emergency hatch for each token.
@@ -352,12 +356,14 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
352
356
  /// @param claimData The terminal token, merkle tree leaf, and proof for the claim.
353
357
  function exitThroughEmergencyHatch(JBClaim calldata claimData) external override {
354
358
  // Does all the needed validation to ensure that the claim is valid *and* that claiming through the emergency
355
- // hatch is allowed.
359
+ // hatch is allowed. The leaf hash covers `metadata` so a remote-attribution leaf is only exitable if the
360
+ // emergency exiter knows the exact `metadata` value the origin committed to.
356
361
  _validateForEmergencyExit({
357
362
  projectTokenCount: claimData.leaf.projectTokenCount,
358
363
  terminalToken: claimData.token,
359
364
  terminalTokenAmount: claimData.leaf.terminalTokenAmount,
360
365
  beneficiary: claimData.leaf.beneficiary,
366
+ metadata: claimData.leaf.metadata,
361
367
  index: claimData.leaf.index,
362
368
  leaves: claimData.proof
363
369
  });
@@ -532,7 +538,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
532
538
  uint256 projectTokenCount,
533
539
  bytes32 beneficiary,
534
540
  uint256 minTokensReclaimed,
535
- address token
541
+ address token,
542
+ bytes32 metadata
536
543
  )
537
544
  external
538
545
  override
@@ -564,12 +571,15 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
564
571
  projectToken: projectToken, count: projectTokenCount, token: token, minTokensReclaimed: minTokensReclaimed
565
572
  });
566
573
 
567
- // Insert the item into the outbox tree for the terminal `token`.
574
+ // Insert the item into the outbox tree for the terminal `token`. The `metadata` field travels inside the leaf
575
+ // hash so receivers can read attribution context from a proven claim — the sucker protocol itself never
576
+ // inspects it.
568
577
  _insertIntoTree({
569
578
  projectTokenCount: projectTokenCount,
570
579
  token: token,
571
580
  terminalTokenAmount: terminalTokenAmount,
572
- beneficiary: beneficiary
581
+ beneficiary: beneficiary,
582
+ metadata: metadata
573
583
  });
574
584
  }
575
585
 
@@ -586,9 +596,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
586
596
 
587
597
  // The caller must be the project owner or have the `SET_SUCKER_DEPRECATION` permission from them.
588
598
  _requirePermissionFrom({
589
- account: PROJECTS.ownerOf(_projectId),
590
- projectId: _projectId,
591
- permissionId: JBPermissionIds.SET_SUCKER_DEPRECATION
599
+ account: _ownerOf(_projectId), projectId: _projectId, permissionId: JBPermissionIds.SET_SUCKER_DEPRECATION
592
600
  });
593
601
 
594
602
  // This is the earliest time for when the sucker can be considered deprecated.
@@ -996,16 +1004,20 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
996
1004
  uint256 projectTokenCount,
997
1005
  address token,
998
1006
  uint256 terminalTokenAmount,
999
- bytes32 beneficiary
1007
+ bytes32 beneficiary,
1008
+ bytes32 metadata
1000
1009
  )
1001
1010
  internal
1002
1011
  {
1003
1012
  // Guard against amounts that would overflow uint128 on SVM (INTEROP-5).
1004
1013
  if (terminalTokenAmount > type(uint128).max) revert JBSucker_AmountExceedsUint128(terminalTokenAmount);
1005
1014
  if (projectTokenCount > type(uint128).max) revert JBSucker_AmountExceedsUint128(projectTokenCount);
1006
- // Build a hash based on the token amounts and the beneficiary.
1015
+ // Build a hash based on the token amounts, the beneficiary, and the attribution metadata.
1007
1016
  bytes32 hashed = _buildTreeHash({
1008
- projectTokenCount: projectTokenCount, terminalTokenAmount: terminalTokenAmount, beneficiary: beneficiary
1017
+ projectTokenCount: projectTokenCount,
1018
+ terminalTokenAmount: terminalTokenAmount,
1019
+ beneficiary: beneficiary,
1020
+ metadata: metadata
1009
1021
  });
1010
1022
 
1011
1023
  // Get the outbox in storage.
@@ -1023,6 +1035,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1023
1035
  root: _computeOutboxRoot(outbox.tree),
1024
1036
  projectTokenCount: projectTokenCount,
1025
1037
  terminalTokenAmount: terminalTokenAmount,
1038
+ metadata: metadata,
1026
1039
  caller: _msgSender()
1027
1040
  });
1028
1041
  }
@@ -1064,7 +1077,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1064
1077
 
1065
1078
  // The registry can map during authorized deployment. Otherwise, require the project's mapping permission.
1066
1079
  _requirePermissionAllowingOverrideFrom({
1067
- account: PROJECTS.ownerOf(_projectId),
1080
+ account: _ownerOf(_projectId),
1068
1081
  projectId: _projectId,
1069
1082
  permissionId: JBPermissionIds.MAP_SUCKER_TOKEN,
1070
1083
  alsoGrantAccessIf: _msgSender() == address(REGISTRY)
@@ -1170,7 +1183,9 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1170
1183
  // Record the balance before the cash out for the sanity check.
1171
1184
  uint256 balanceBefore = _balanceOf({token: token, addr: address(this)});
1172
1185
 
1173
- // Cash out the project tokens for terminal tokens.
1186
+ // Cash out the project tokens for terminal tokens. Suckers are a transparent value-mover (the bridge
1187
+ // accounting is the entirety of their function) — they're not a fee-paying entry point for any referrer,
1188
+ // so `referralProjectId: 0` is correct.
1174
1189
  reclaimedAmount = terminal.cashOutTokensOf({
1175
1190
  holder: address(this),
1176
1191
  projectId: cachedProjectId,
@@ -1178,7 +1193,8 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1178
1193
  tokenToReclaim: token,
1179
1194
  minTokensReclaimed: minTokensReclaimed,
1180
1195
  beneficiary: payable(address(this)),
1181
- metadata: bytes("")
1196
+ metadata: bytes(""),
1197
+ referralProjectId: 0
1182
1198
  });
1183
1199
 
1184
1200
  // Sanity check to make sure we received the expected amount.
@@ -1289,6 +1305,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1289
1305
  address terminalToken,
1290
1306
  uint256 terminalTokenAmount,
1291
1307
  bytes32 beneficiary,
1308
+ bytes32 metadata,
1292
1309
  uint256 index,
1293
1310
  bytes32[_TREE_DEPTH] calldata leaves
1294
1311
  )
@@ -1312,6 +1329,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1312
1329
  projectTokenCount: projectTokenCount,
1313
1330
  terminalTokenAmount: terminalTokenAmount,
1314
1331
  beneficiary: beneficiary,
1332
+ metadata: metadata,
1315
1333
  index: index,
1316
1334
  leaves: leaves
1317
1335
  });
@@ -1331,6 +1349,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1331
1349
  uint256 projectTokenCount,
1332
1350
  uint256 terminalTokenAmount,
1333
1351
  bytes32 beneficiary,
1352
+ bytes32 metadata,
1334
1353
  uint256 index,
1335
1354
  bytes32[_TREE_DEPTH] calldata leaves
1336
1355
  )
@@ -1341,7 +1360,10 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1341
1360
  // Delegates to JBSuckerLib (via DELEGATECALL) to keep MerkleLib.branchRoot bytecode out of each sucker.
1342
1361
  bytes32 root = JBSuckerLib.computeBranchRoot({
1343
1362
  item: _buildTreeHash({
1344
- projectTokenCount: projectTokenCount, terminalTokenAmount: terminalTokenAmount, beneficiary: beneficiary
1363
+ projectTokenCount: projectTokenCount,
1364
+ terminalTokenAmount: terminalTokenAmount,
1365
+ beneficiary: beneficiary,
1366
+ metadata: metadata
1345
1367
  }),
1346
1368
  branch: leaves,
1347
1369
  index: index
@@ -1385,6 +1407,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1385
1407
  address terminalToken,
1386
1408
  uint256 terminalTokenAmount,
1387
1409
  bytes32 beneficiary,
1410
+ bytes32 metadata,
1388
1411
  uint256 index,
1389
1412
  bytes32[_TREE_DEPTH] calldata leaves
1390
1413
  )
@@ -1435,6 +1458,7 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1435
1458
  projectTokenCount: projectTokenCount,
1436
1459
  terminalTokenAmount: terminalTokenAmount,
1437
1460
  beneficiary: beneficiary,
1461
+ metadata: metadata,
1438
1462
  index: index,
1439
1463
  leaves: leaves
1440
1464
  });
@@ -1482,24 +1506,27 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1482
1506
  /// @param projectTokenCount The number of project tokens to cash out.
1483
1507
  /// @param terminalTokenAmount The amount of terminal tokens to reclaim from the cash out.
1484
1508
  /// @param beneficiary The beneficiary which will receive the project tokens (bytes32 for cross-VM compatibility).
1509
+ /// @param metadata Opaque caller-defined attribution payload travelling inside the leaf hash.
1485
1510
  /// @return hash The keccak256 hash of the leaf data.
1486
1511
  function _buildTreeHash(
1487
1512
  uint256 projectTokenCount,
1488
1513
  uint256 terminalTokenAmount,
1489
- bytes32 beneficiary
1514
+ bytes32 beneficiary,
1515
+ bytes32 metadata
1490
1516
  )
1491
1517
  internal
1492
1518
  pure
1493
1519
  returns (bytes32 hash)
1494
1520
  {
1495
- // All three arguments are 32 bytes — hash from free memory to avoid abi.encode allocation overhead.
1521
+ // All four arguments are 32 bytes — hash from free memory to avoid abi.encode allocation overhead.
1496
1522
  // forge-lint: disable-next-line(asm-keccak256)
1497
1523
  assembly {
1498
1524
  let ptr := mload(0x40)
1499
1525
  mstore(ptr, projectTokenCount)
1500
1526
  mstore(add(ptr, 0x20), terminalTokenAmount)
1501
1527
  mstore(add(ptr, 0x40), beneficiary)
1502
- hash := keccak256(ptr, 0x60)
1528
+ mstore(add(ptr, 0x60), metadata)
1529
+ hash := keccak256(ptr, 0x80)
1503
1530
  }
1504
1531
  }
1505
1532
 
@@ -1543,6 +1570,20 @@ abstract contract JBSucker is ERC2771Context, JBPermissioned, Initializable, ERC
1543
1570
  return ERC2771Context._msgSender();
1544
1571
  }
1545
1572
 
1573
+ /// @notice Resolve the current owner of the project this sucker belongs to.
1574
+ /// @dev `PROJECTS.ownerOf(...)` is the source of truth for "project owner" permission checks; we hit it from
1575
+ /// every permission-gated entrypoint (`enableEmergencyHatchFor`, `setDeprecation`, `_mapToken`). Routing all
1576
+ /// three through this internal helper emits the abi-encode + STATICCALL + return-decode sequence once in the
1577
+ /// child contract's bytecode instead of inlining it at each call site, which is what keeps `JBSwapCCIPSucker`
1578
+ /// under the EIP-170 limit after the leaf-`metadata` thread-through landed.
1579
+ /// @param forProjectId The project ID to look up — always the sucker's own `projectId()`, but accepted as a
1580
+ /// parameter so callers can pass the cached local they already computed (avoiding a redundant `projectId()`
1581
+ /// call against the read-only registry).
1582
+ /// @return owner The address currently registered as the project's ERC-721 holder.
1583
+ function _ownerOf(uint256 forProjectId) internal view returns (address owner) {
1584
+ return PROJECTS.ownerOf(forProjectId);
1585
+ }
1586
+
1546
1587
  /// @notice Retain a failed `toRemoteFee` payment for later caller refund.
1547
1588
  /// @param account The account that can reclaim the retained fee.
1548
1589
  /// @param amount The retained fee amount.
@@ -485,7 +485,7 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
485
485
  /// @notice Deploy one or more cross-chain suckers for a project in a single transaction. Each sucker is created via
486
486
  /// its deployer, registered in this registry, and immediately configured with its token mappings. Multiple suckers
487
487
  /// targeting the same peer chain are allowed for bridge resilience. The caller must have `DEPLOY_SUCKERS`
488
- /// permission, and this registry must hold `MAP_SUCKER_TOKEN` permission for the project.
488
+ /// permission, which also authorizes the initial token mappings in each deployment configuration.
489
489
  /// @param projectId The ID of the project to deploy suckers for.
490
490
  /// @param salt The salt used to deploy the contract. For the suckers to be peers, this must be the same value on
491
491
  /// each chain where suckers are deployed.
@@ -30,6 +30,7 @@ interface IJBSucker is IERC165 {
30
30
  uint256 projectTokenCount,
31
31
  uint256 terminalTokenAmount,
32
32
  uint256 index,
33
+ bytes32 metadata,
33
34
  address caller
34
35
  );
35
36
 
@@ -50,6 +51,7 @@ interface IJBSucker is IERC165 {
50
51
  bytes32 root,
51
52
  uint256 projectTokenCount,
52
53
  uint256 terminalTokenAmount,
54
+ bytes32 metadata,
53
55
  address caller
54
56
  );
55
57
 
@@ -191,11 +193,16 @@ interface IJBSucker is IERC165 {
191
193
  /// @param beneficiary The beneficiary on the remote chain (bytes32 for cross-VM compatibility).
192
194
  /// @param minTokensReclaimed The minimum terminal tokens to receive from the cash out.
193
195
  /// @param token The terminal token to cash out into.
196
+ /// @param metadata Opaque caller-defined attribution payload included in the leaf hash. The sucker protocol does
197
+ /// not inspect this value — it's covered by the merkle root, so the destination contract that consumes the claim
198
+ /// can
199
+ /// trust it once the proof verifies. Pass `bytes32(0)` for an ordinary bridge with no attribution context.
194
200
  function prepare(
195
201
  uint256 projectTokenCount,
196
202
  bytes32 beneficiary,
197
203
  uint256 minTokensReclaimed,
198
- address token
204
+ address token,
205
+ bytes32 metadata
199
206
  )
200
207
  external;
201
208
 
@@ -130,8 +130,8 @@ interface IJBSuckerRegistry {
130
130
  function allowSuckerDeployers(address[] calldata deployers) external;
131
131
 
132
132
  /// @notice Deploy one or more suckers for the specified project.
133
- /// @dev This call also applies each configuration's token mappings on the deployed suckers. Projects using this
134
- /// path need the registry to be able to satisfy the corresponding `MAP_SUCKER_TOKEN` checks.
133
+ /// @dev This call also applies each configuration's token mappings on the deployed suckers. `DEPLOY_SUCKERS`
134
+ /// authorizes those initial mappings; use `MAP_SUCKER_TOKEN` for post-deployment mapping changes.
135
135
  /// @param projectId The ID of the project to deploy suckers for.
136
136
  /// @param salt The salt used for deterministic deployment.
137
137
  /// @param configurations The deployer configs to use.
@@ -6,9 +6,15 @@ pragma solidity ^0.8.0;
6
6
  /// @custom:member beneficiary The beneficiary of the leaf.
7
7
  /// @custom:member projectTokenCount The number of project tokens to claim.
8
8
  /// @custom:member terminalTokenAmount The amount of terminal tokens to claim.
9
+ /// @custom:member metadata Opaque, caller-defined attribution payload that travels with the leaf inside the merkle
10
+ /// root. Use cases include cross-chain referral split hooks tagging a leaf with `(originChainId, referralProjectId)`
11
+ /// so the destination contract can settle the bridged value atomically. The sucker protocol itself never inspects
12
+ /// this field — it's covered by the leaf hash, so receivers can trust the value once the merkle proof verifies.
13
+ /// Pass `bytes32(0)` when no attribution context is needed.
9
14
  struct JBLeaf {
10
15
  uint256 index;
11
16
  bytes32 beneficiary;
12
17
  uint256 projectTokenCount;
13
18
  uint256 terminalTokenAmount;
19
+ bytes32 metadata;
14
20
  }
package/CHANGELOG.md DELETED
@@ -1,81 +0,0 @@
1
- # Changelog
2
-
3
- ## Scope
4
-
5
- This file describes the verified change from `nana-suckers-v5` to the current `nana-suckers-v6` repo.
6
-
7
- ## Current v6 surface
8
-
9
- - `JBSucker`
10
- - `JBSuckerRegistry`
11
- - `JBOptimismSucker`
12
- - `JBArbitrumSucker`
13
- - `JBBaseSucker`
14
- - `JBCCIPSucker`
15
- - `JBCeloSucker`
16
- - the deployers, structs, and interfaces under `src/`
17
-
18
- ## 0.0.46 — Bump nana-core-v6 to 0.0.53
19
-
20
- `@bananapus/core-v6@0.0.53` ([nana-core-v6 PR #145](https://github.com/Bananapus/nana-core-v6/pull/145)) drops the `via_ir` requirement on `JBCashOutHookSpecsLib`, which lets this package consume the cross-project cashout work (`payAfterCashOutTokensOf` / `addToBalanceAfterCashOutTokensOf`) without needing `via_ir = true` in its own foundry profile.
21
-
22
- - No src changes — suckers doesn't reference `IJBFeeTerminal.FEE()` or any of the touched core surfaces.
23
- - All `JBRulesetMetadata` test literals patched to include `pauseCrossProjectFeeFreeInflows: false`.
24
-
25
- `package.json`: version `0.0.44 → 0.0.46` (skipping 0.0.45 because nothing shipped at that intermediate revision), core dep `^0.0.48 → ^0.0.53`.
26
-
27
- ## Summary
28
-
29
- - Cross-chain identifiers are now modeled for a wider address space. The v6 repo uses `bytes32` where the v5 repo used EVM `address` assumptions.
30
- - Message handling is versioned instead of implicitly trusting an older fixed format.
31
- - The anti-spam and fee model changed materially. v5's per-token minimum-bridge assumptions were replaced by a registry-level `toRemoteFee` flow in v6.
32
- - The old manual add-to-balance mode is gone from the current repo.
33
- - Celo support is now part of the repo's first-class contract set.
34
- - The repo moved from the v5 `0.8.23` baseline to `0.8.28`.
35
-
36
- ## Verified deltas
37
-
38
- - `IJBSucker.peer()` now returns `bytes32`.
39
- - `IJBSucker.prepare(...)` now takes a `bytes32 beneficiary`.
40
- - `Claimed` and `InsertToOutboxTree` changed their `beneficiary` field from `address` to `bytes32`.
41
- - The `Claimed` event no longer carries the old `autoAddedToBalance` boolean.
42
- - The public `ADD_TO_BALANCE_MODE()` surface and the manual mode path are gone from the interface.
43
- - `StaleRootRejected(...)` is a new event on the interface.
44
-
45
- ## Breaking ABI changes
46
-
47
- - `JBRemoteToken.addr` changed from `address` to `bytes32`.
48
- - `JBTokenMapping.remoteToken` changed from `address` to `bytes32`.
49
- - `JBMessageRoot` gained `version` and changed `token` from `address` to `bytes32`.
50
- - `IJBSucker.peer()` changed return type.
51
- - `IJBSucker.prepare(...)` changed parameter type for `beneficiary`.
52
- - The manual add-to-balance mode surface was removed.
53
-
54
- ## Indexer impact
55
-
56
- - `Claimed` and `InsertToOutboxTree` require schema changes because `beneficiary` is no longer an EVM address.
57
- - Remote token and peer identifiers should be stored as raw 32-byte values.
58
- - `StaleRootRejected` is new and can be used to monitor out-of-order or duplicate delivery attempts.
59
-
60
- ## Migration notes
61
-
62
- - Treat every cross-chain identifier schema as migrated, including indexers and bridge metadata.
63
- - Rebuild integrations around the current fee and registry model. Old `minBridgeAmount` assumptions are stale.
64
- - Use the current v6 structs and events for ABI regeneration. This repo has too many widened fields for manual patching to be safe.
65
-
66
- ## ABI appendix
67
-
68
- - Changed functions
69
- - `peer() -> bytes32`
70
- - `prepare(..., bytes32 beneficiary, ...)`
71
- - Changed events
72
- - `Claimed`
73
- - `InsertToOutboxTree`
74
- - Added events
75
- - `StaleRootRejected`
76
- - Removed surface
77
- - manual add-to-balance mode / `ADD_TO_BALANCE_MODE()`
78
- - Changed structs
79
- - `JBRemoteToken`
80
- - `JBTokenMapping`
81
- - `JBMessageRoot`