@bananapus/distributor-v6 0.0.13 → 0.0.16

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.16 — Bump v6 deps to nana-core-v6 0.0.53 cohort
4
+
5
+ - `@bananapus/core-v6`: `^0.0.48 → ^0.0.53` ([PR #145](https://github.com/Bananapus/nana-core-v6/pull/145)).
6
+ - `@bananapus/721-hook-v6`: `^0.0.47 → ^0.0.50`.
7
+ - `@bananapus/permission-ids-v6`: `^0.0.22 → ^0.0.25`.
8
+ - All `JBRulesetMetadata` test literals patched to include `pauseCrossProjectFeeFreeInflows: false`.
9
+
3
10
  ## 0.0.1
4
11
 
5
12
  Initial release of the Juicebox V6 distributor system.
package/foundry.toml CHANGED
@@ -1,5 +1,6 @@
1
1
  [profile.default]
2
2
  solc = '0.8.28'
3
+ bytecode_hash = "none"
3
4
  evm_version = 'cancun'
4
5
  optimizer_runs = 200
5
6
  libs = ["node_modules", "lib"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/distributor-v6",
3
- "version": "0.0.13",
3
+ "version": "0.0.16",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,9 +26,9 @@
26
26
  "deploy:testnets": "source ./.env && npx sphinx propose ./script/Deploy.s.sol --networks testnets"
27
27
  },
28
28
  "dependencies": {
29
- "@bananapus/721-hook-v6": "0.0.47",
30
- "@bananapus/core-v6": "0.0.43",
31
- "@bananapus/permission-ids-v6": "0.0.22",
29
+ "@bananapus/721-hook-v6": "^0.0.50",
30
+ "@bananapus/core-v6": "^0.0.53",
31
+ "@bananapus/permission-ids-v6": "^0.0.25",
32
32
  "@openzeppelin/contracts": "5.6.1",
33
33
  "@prb/math": "4.1.1"
34
34
  },
@@ -107,6 +107,14 @@ abstract contract JBDistributor is IJBDistributor {
107
107
  mapping(address hook => mapping(IERC20 token => mapping(uint256 round => JBTokenSnapshotData snapshot))) internal
108
108
  _snapshotAtRoundOf;
109
109
 
110
+ /// @notice Whether a snapshot has been taken for a given (hook, token, round).
111
+ /// @dev Required because a snapshot can legitimately store `{balance: 0, vestingAmount: 0}`,
112
+ /// so a zero balance is not a usable sentinel for "uninitialized".
113
+ /// @custom:param hook The hook the snapshot is for.
114
+ /// @custom:param token The address of the token claimed and vested.
115
+ /// @custom:param round The round to which the data applies.
116
+ mapping(address hook => mapping(IERC20 token => mapping(uint256 round => bool))) internal _snapshotInitializedFor;
117
+
110
118
  //*********************************************************************//
111
119
  // -------------------------- constructor ---------------------------- //
112
120
  //*********************************************************************//
@@ -469,18 +477,20 @@ abstract contract JBDistributor is IJBDistributor {
469
477
  // Keep a reference to the current round.
470
478
  uint256 round = currentRound();
471
479
 
472
- // Keep a reference to the token's snapshot.
473
- snapshot = _snapshotAtRoundOf[hook][token][round];
474
-
475
- // If a snapshot was already taken at this cycle, do not take a new one.
476
- if (snapshot.balance != 0) return snapshot;
480
+ // If a snapshot was already taken at this round, do not take a new one. The init flag must be used as the
481
+ // sentinel: a zero balance is a valid snapshot value (round started with no funded balance), not a signal
482
+ // to re-snapshot. Re-snapshotting would let mid-round deposits leak into the current round's allocation.
483
+ if (_snapshotInitializedFor[hook][token][round]) {
484
+ return _snapshotAtRoundOf[hook][token][round];
485
+ }
477
486
 
478
487
  // Take a snapshot using the hook's tracked balance.
479
488
  snapshot =
480
489
  JBTokenSnapshotData({balance: _balanceOf[hook][token], vestingAmount: totalVestingAmountOf[hook][token]});
481
490
 
482
- // Store the snapshot.
491
+ // Store the snapshot and mark it initialized.
483
492
  _snapshotAtRoundOf[hook][token][round] = snapshot;
493
+ _snapshotInitializedFor[hook][token][round] = true;
484
494
 
485
495
  emit SnapshotCreated({
486
496
  hook: hook, round: round, token: token, balance: snapshot.balance, vestingAmount: snapshot.vestingAmount
@@ -674,6 +684,14 @@ abstract contract JBDistributor is IJBDistributor {
674
684
  // Keep a reference to the amount of tokens being claimed.
675
685
  uint256 tokenAmount = mulDiv(distributable, _tokenStake({hook: hook, tokenId: tokenId}), totalStakeAmount);
676
686
 
687
+ // Skip zero-amount entries to prevent stalling latestVestedIndexOf advancement.
688
+ if (tokenAmount == 0) {
689
+ unchecked {
690
+ ++j;
691
+ }
692
+ continue;
693
+ }
694
+
677
695
  // Add to the list of vesting data.
678
696
  vestings.push(JBVestingData({releaseRound: vestingReleaseRound, amount: tokenAmount, shareClaimed: 0}));
679
697