@bananapus/distributor-v6 0.0.36 → 0.0.38

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/README.md CHANGED
@@ -30,7 +30,7 @@ Use this repo when the problem is "how do we distribute already-owned assets ove
30
30
 
31
31
  If the issue is "where did the project's value come from?" start in `nana-core-v6`, `nana-721-hook-v6`, or the upstream repo that minted or received the assets first.
32
32
 
33
- ## Key Contracts
33
+ ## Key contracts
34
34
 
35
35
  | Contract | Role |
36
36
  | --- | --- |
@@ -38,7 +38,7 @@ If the issue is "where did the project's value come from?" start in `nana-core-v
38
38
  | `JBTokenDistributor` | ERC-20 distributor keyed to `IVotes` checkpointed voting power. |
39
39
  | `JB721Distributor` | NFT-aware distributor keyed to checkpointed voting power from the hook's `CHECKPOINTS()` module. Only NFTs held at the funded round's snapshot block are eligible. |
40
40
 
41
- ## Mental Model
41
+ ## Mental model
42
42
 
43
43
  1. a project funds the distributor, often through a payout split
44
44
  2. accepted funding is assigned to the current reward round for the chosen token or 721 stake source
@@ -51,14 +51,14 @@ If the issue is "where did the project's value come from?" start in `nana-core-v
51
51
 
52
52
  This repo does not explain why an allocation exists. It only defines how funded inventory is handed out.
53
53
 
54
- ## Read These Files First
54
+ ## Read these files first
55
55
 
56
56
  1. `src/interfaces/IJBDistributor.sol`
57
57
  2. `src/JBDistributor.sol`
58
58
  3. `src/JBTokenDistributor.sol`
59
59
  4. `src/JB721Distributor.sol`
60
60
 
61
- ## Integration Traps
61
+ ## Integration traps
62
62
 
63
63
  - distribution correctness depends on the distributor actually holding the assets it is expected to vest
64
64
  - ERC-20 and ERC-721 distributions share historical reward-round accounting, but claim authority differs:
@@ -87,14 +87,14 @@ This repo does not explain why an allocation exists. It only defines how funded
87
87
  - snapshot timing is part of the trusted surface
88
88
  - this repo settles distributions, but it does not prove the upstream entitlement math was correct
89
89
 
90
- ## Where State Lives
90
+ ## Where state lives
91
91
 
92
92
  - round and vesting state: `JBDistributor`
93
93
  - historical reward-round inputs: `JBRewardRoundData`
94
94
  - vesting schedule state: `JBVestingData`
95
95
  - asset-specific claim behavior: the concrete distributor
96
96
 
97
- ## High-Signal Tests
97
+ ## High-signal tests
98
98
 
99
99
  1. `test/JBTokenDistributor.t.sol`
100
100
  2. `test/JB721Distributor.t.sol`
@@ -121,7 +121,7 @@ Useful scripts:
121
121
  - `npm run deploy:mainnets`
122
122
  - `npm run deploy:testnets`
123
123
 
124
- ## Repository Layout
124
+ ## Repository layout
125
125
 
126
126
  ```text
127
127
  src/
@@ -136,7 +136,7 @@ script/
136
136
  Deploy.s.sol
137
137
  ```
138
138
 
139
- ## Risks And Notes
139
+ ## Risks and notes
140
140
 
141
141
  - distributors are only as trustworthy as the vesting parameters and funding they receive
142
142
  - operational mistakes often come from funding the wrong asset or underfunding the distributor
@@ -144,7 +144,7 @@ script/
144
144
  - deployers that set a nonzero claim duration should choose a window long enough for expected claimants, because
145
145
  expired unclaimed rewards can be recycled by anyone
146
146
 
147
- ## For AI Agents
147
+ ## For AI agents
148
148
 
149
149
  - Treat this repo as distribution plumbing, not as the source of upstream entitlement math.
150
150
  - Read both the ERC-20 and ERC-721 tests before claiming the flows are equivalent.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/distributor-v6",
3
- "version": "0.0.36",
3
+ "version": "0.0.38",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,12 +24,12 @@
24
24
  "deploy:testnets": "source ./.env && npx sphinx propose ./script/Deploy.s.sol --networks testnets"
25
25
  },
26
26
  "dependencies": {
27
- "@bananapus/721-hook-v6": "^0.0.63",
28
- "@bananapus/core-v6": "^0.0.72",
29
- "@bananapus/permission-ids-v6": "^0.0.27",
27
+ "@bananapus/721-hook-v6": "^0.0.65",
28
+ "@bananapus/core-v6": "^0.0.78",
29
+ "@bananapus/permission-ids-v6": "^0.0.28",
30
30
  "@openzeppelin/contracts": "5.6.1",
31
31
  "@prb/math": "4.1.1",
32
- "@rev-net/core-v6": "^0.0.75"
32
+ "@rev-net/core-v6": "^0.0.84"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@sphinx-labs/plugins": "0.33.3"
@@ -20,7 +20,7 @@
20
20
  | 721 reward shares look diluted | Burned supply was not excluded correctly or token-to-tier mapping is wrong |
21
21
  | Split-hook funding credits the wrong amount | The caller did not grant a sufficient ERC-20 allowance before calling `processSplitWith` |
22
22
 
23
- ## Read Next
23
+ ## Read next
24
24
 
25
25
  - [`script/Deploy.s.sol`](../script/Deploy.s.sol) when the failure might be deployment config rather than distributor math.
26
26
  - [`test/invariant/JB721DistributorInvariant.t.sol`](../test/invariant/JB721DistributorInvariant.t.sol) when a local patch looks safe but may have broken a longer-lived accounting invariant.
@@ -163,6 +163,7 @@ abstract contract JBDistributor is IJBDistributor {
163
163
 
164
164
  /// @notice The block number recorded as the snapshot point for each round.
165
165
  /// @dev Set to `block.number - 1` on first interaction in a round, so that `IVotes.getPastVotes` works.
166
+ /// @custom:param round The round whose snapshot block is being recorded.
166
167
  mapping(uint256 round => uint256) public override roundSnapshotBlock;
167
168
 
168
169
  /// @notice Reward data assigned to each funding round.
@@ -296,7 +297,7 @@ abstract contract JBDistributor is IJBDistributor {
296
297
  }
297
298
 
298
299
  /// @notice Recycle unclaimed rewards from expired reward rounds into the current reward round.
299
- /// @dev The selector name is kept for compatibility with existing keeper integrations.
300
+ /// @dev Recycling is permissionless; any keeper or frontend can sweep an expired round.
300
301
  /// @param hook The hook whose expired rewards should be recycled.
301
302
  /// @param token The reward token to recycle.
302
303
  /// @param rounds The reward rounds to recycle.
@@ -633,7 +634,7 @@ abstract contract JBDistributor is IJBDistributor {
633
634
  // Before collecting, bring the token IDs current by starting vesting for any past reward rounds.
634
635
  _claimPastRewards({hook: hook, groupId: groupId, tokenIds: tokenIds, tokens: tokens});
635
636
 
636
- // Release whatever portion of existing vesting entries has unlocked by this round.
637
+ // Release whatever portion of vesting entries has unlocked by this round.
637
638
  _unlockRewards({
638
639
  hook: hook, groupId: groupId, tokenIds: tokenIds, tokens: tokens, beneficiary: beneficiary, ownerClaim: true
639
640
  });
@@ -911,7 +912,7 @@ abstract contract JBDistributor is IJBDistributor {
911
912
  revert JBDistributor_UnexpectedNativeValue({msgValue: msg.value, token: loan.sourceToken});
912
913
  }
913
914
 
914
- // Pull the exact current payoff from the caller. Existing distributor inventory must not cover a shortfall.
915
+ // Pull the exact current payoff from the caller. Distributor inventory must not cover a shortfall.
915
916
  IERC20 sourceToken = IERC20(loan.sourceToken);
916
917
  uint256 sourceBalanceBefore = sourceToken.balanceOf(address(this));
917
918
  sourceToken.safeTransferFrom({from: msg.sender, to: address(this), value: repayBorrowAmount});
@@ -1263,7 +1264,7 @@ abstract contract JBDistributor is IJBDistributor {
1263
1264
  /// @param round The reward round.
1264
1265
  /// @return claimDeadline The deadline timestamp. Zero means no expiration.
1265
1266
  function _claimDeadlineFor(uint256 round) internal view returns (uint48 claimDeadline) {
1266
- // Zero duration keeps the round non-expiring and backward compatible with existing fund paths.
1267
+ // A zero claim duration means the round never expires.
1267
1268
  if (CLAIM_DURATION == 0) return 0;
1268
1269
 
1269
1270
  // Start the window at the next round boundary, when the funded round first becomes claimable.
@@ -6,7 +6,8 @@ import {mulDiv} from "@prb/math/src/Common.sol";
6
6
  /// @notice Pure helpers for the distributor's linear vesting arithmetic.
7
7
  library JBVestingMath {
8
8
  /// @notice The share still locked for a vesting entry at `currentRound`.
9
- /// @dev Mirrors the distributor's existing linear vesting formula. Callers maintain the invariant that
9
+ /// @dev Linear release: the locked share shrinks one `maxShare/vestingRounds` step per round. Callers maintain
10
+ /// the invariant that
10
11
  /// `releaseRound - currentRound <= vestingRounds` whenever `releaseRound > currentRound`.
11
12
  /// @param releaseRound The round when the entry is fully unlocked.
12
13
  /// @param currentRound The current distributor round.
@@ -1,6 +1,7 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.0;
3
3
 
4
+ /// @notice Parameters describing one lazy claim of completed reward rounds into a fresh vesting entry.
4
5
  /// @custom:member hook The stake source whose historical rewards are being claimed.
5
6
  /// @custom:member groupId The reward group being claimed (0 = the default group).
6
7
  /// @custom:member tierIds The tier set defining the group (empty for the default group); used to filter eligible
@@ -3,6 +3,7 @@ pragma solidity ^0.8.0;
3
3
 
4
4
  import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5
5
 
6
+ /// @notice Parameters describing one round's reward allocation while vesting begins.
6
7
  /// @custom:member hook The stake source whose rewards are being vested.
7
8
  /// @custom:member groupId The reward group being claimed (0 = the default group).
8
9
  /// @custom:member tierIds The tier set defining the group (empty for the default group); used to filter eligible