split_lib¶
Pure BPS-splitting library used by EmissionRouter and GaugeWeightRouter. Not deployed — @internal @pure helpers compile into each consumer.
Source: khomdev-veforge/src/split_lib.vy (Vyper 0.4.x)
Consumers: EmissionRouter.distribute · GaugeWeightRouter.poke (inline equivalent)
Implementation overview¶
- No storage — all functions
@internal @pure - proportional_split — normalize weights onto pool; last slot absorbs dust so sum equals pool exactly
- weighted_distribution — like proportional but skips slices below
min_slice; returns dust for caller to retain
flowchart TD
W[weights + total_weight + pool] --> PS[proportional_split]
W --> WD[weighted_distribution]
PS --> ER[EmissionRouter distribute]
WD --> ER
Constants¶
| Name | Value | Role |
|---|---|---|
MAX_BPS |
10000 | Denominator mirror |
Internal functions¶
proportional_split¶
split_lib.proportional_split(weights, total_weight, pool) -> DynArray[uint256, 32]
Normalize per-item weights onto pool. Last slot absorbs floor-division dust so returned array sums to pool exactly.
| Param | Type | Description |
|---|---|---|
weights |
DynArray[uint256, 32] |
Per-item weights (any scale; ratio matters) |
total_weight |
uint256 |
Sum of weights (caller-provided) |
pool |
uint256 |
Total pie to distribute |
Returns: DynArray[uint256, 32] — proportional shares; Σ == pool.
Access: @internal @pure — inlined in consumer.
Source (khomdev-veforge/src/split_lib.vy:29-79):
@internal
@pure
def proportional_split(weights: DynArray[uint256, 32], total_weight: uint256, pool: uint256) -> DynArray[uint256, 32]:
if i == last:
share = pool - running # dust to last slot
else:
share = weights[i] * pool // total_weight
Example:
# EmissionRouter uses weighted_distribution instead when min_slice = num_epochs
shares = split_lib.proportional_split(weights, total, bal)
Cross-links: weighted_distribution
weighted_distribution¶
split_lib.weighted_distribution(weights, total_weight, pool, min_slice) -> (DynArray[uint256, 32], uint256)
Like proportional_split but items below min_slice get 0; skipped amount returned as dust.
| Param | Type | Description |
|---|---|---|
weights |
DynArray[uint256, 32] |
Per-item weights |
total_weight |
uint256 |
Sum of weights |
pool |
uint256 |
Total to distribute |
min_slice |
uint256 |
Minimum viable slice (e.g. num_epochs) |
Returns: (allocations, dust) — allocations same length as weights; sub-threshold entries are 0.
Access: @internal @pure — inlined in EmissionRouter.
Source (khomdev-veforge/src/split_lib.vy:82-131):
@internal
@pure
def weighted_distribution(weights, total_weight, pool, min_slice) -> (DynArray[uint256, 32], uint256):
amount: uint256 = weights[i] * pool // total_weight
if amount < min_slice:
dust += amount
result.append(0)
else:
result.append(amount)
return (result, dust)
Note: EmissionRouter passes min_slice = num_epochs — gauges with indivisible slices are skipped; dust stays in router for next distribute.
Cross-links: EmissionRouter.distribute · proportional_split
Cross-links¶
- EmissionRouter · GaugeWeightRouter · Rebalancer (similar allocation math)