Files
node/docs/ECONOMICS.md
Vasanth T d366fc6b97 [codex] chore: add live-safe OSS readiness pass (#14)
* chore: add live-safe OSS readiness pass

* fix(node): verify optional peer signatures during rollout

* docs: rewrite README for node roadmap
2026-05-28 15:34:47 +08:00

157 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# gitlawb economics
How $GITLAWB flows through the protocol and how stakers earn.
---
## TL;DR
- Every protocol fee (5% of completed bounties, plus future services) flows into `GitlawbFeeDistributor` — the protocol's reward wallet.
- Once per week, anyone can call `distribute()` to split the accumulated balance.
- **75%** goes to **node operators** (PoS staking — skin in the game).
- **24%** goes to **user stakers** (tier-weighted passive yield).
- **1%** goes to **the caller** of `distribute()` (keeper reward).
---
## Fee sources
All routed to `GitlawbFeeDistributor`:
| Source | Rate | How it gets there |
|---|---|---|
| Bounty protocol fee | 5% of payout | `GitlawbBounty.treasury` is set to the distributor — arrives on `approveBounty()` |
| Manual deposits (bankr) | variable | `token.transfer(feeDistributor, amount)` — any $GITLAWB sent to the address counts |
| Future: push/PR fees | TBD | node fees collected by operators, routed to distributor |
The distributor is a plain ERC20 holder — anything sent to it is fair game for the weekly split.
---
## The weekly split
```
distribute() — permissionless, enforced ≥ 7 days since last call
├── 1% → msg.sender (keeper reward)
├── 75% → GitlawbNodeStaking (operator PoS rewards)
└── 24% → GitlawbStaking (user tier-weighted rewards)
```
Split is owner-adjustable but capped to ±5% change per update (prevents abrupt reallocations).
---
## Node operator staking (75% track)
**Contract:** `GitlawbNodeStaking.sol`
Node operators **must** stake to run a node and earn rewards.
| Parameter | Value |
|---|---|
| Minimum stake | 10,000 $GITLAWB |
| Heartbeat cadence | 24 hours |
| Inactive threshold | 3 days (no heartbeat → excluded from rewards) |
| Unstake cooldown | 7 days |
**Reward formula** (per node, per weekly distribution):
```
nodeReward_i = nodeShare × (myStake / totalActiveStake) if heartbeat within 3 days
nodeReward_i = 0 otherwise
```
**Worked example — 5 active nodes**, all at 10k stake, weekly pot = 100k $GITLAWB:
- Node share (75%) = 75k
- Total active stake = 50k
- Each node earns: `75k × (10k / 50k)` = **15,000 $GITLAWB/week**
If one node goes offline, the active pool shrinks and remaining nodes earn more — the offline node gets nothing, its share redistributes.
**Skin in the game:** no automatic token slashing in v1, but offline nodes earn zero. Repeated offenses + inflated stake = dead capital.
---
## User staking (24% track)
**Contract:** `GitlawbStaking.sol`
Anyone can stake $GITLAWB for passive yield. Four tiers with multipliers:
| Tier | Min stake | Multiplier |
|---|---|---|
| Observer | 1,000 | 1x |
| Curator | 10,000 | 2x |
| Steward | 100,000 | 4x |
| Validator | 1,000,000 | 8x |
**Reward formula** (per staker, per weekly distribution):
```
userReward_i = userShare × (myStake × myMultiplier / totalWeightedStake)
```
**Worked example — mixed tiers**, weekly pot = 100k → user share = 24k:
| Staker | Stake | Multiplier | Weight |
|---|---|---|---|
| 5× Observer | 1k each | 1x | 5,000 |
| 3× Curator | 10k each | 2x | 60,000 |
| 2× Steward | 100k each | 4x | 800,000 |
| **Total weighted** | | | **865,000** |
- Each Observer: `24k × (1k / 865k)` ≈ **27.7 $GITLAWB/week**
- Each Curator: `24k × (20k / 865k)` ≈ **555 $GITLAWB/week**
- Each Steward: `24k × (400k / 865k)` ≈ **11,098 $GITLAWB/week**
**Unstake cooldown:** 7 days.
---
## Keeper reward (1% track)
The caller of `distribute()` receives 1% of the pot. At 100k weekly, that's 1,000 $GITLAWB.
Why: removes operational burden. Even if the official keeper misses a run, any staker or searcher has financial incentive to call it.
Operators can run a weekly keeper job that calls `distribute()`; the caller wallet self-funds its gas from the 1% reward.
---
## End-to-end flow
```
┌─────────────────────────────────────────┐
│ Fee sources │
│ ┌─────────────┐ ┌─────────────┐ │
│ │Bounty 5% │ │Bankr manual │ ··· │
│ └──────┬──────┘ └──────┬──────┘ │
└─────────┼─────────────────┼─────────────┘
↓ ↓
┌─────────────────────────────────────────┐
│ GitlawbFeeDistributor │
│ (the protocol reward wallet) │
└──────────────────┬──────────────────────┘
│
distribute() │ weekly, permissionless
↓
┌──────────────────────┼──────────────────────┐
│ │ │
┌────▼────┐ ┌────────▼────────┐ ┌──────▼──────┐
│ 1% │ │ 75% │ │ 24% │
│ caller │ │ NodeStaking │ │ UserStaking │
└─────────┘ │ (pro-rata: │ │ (pro-rata: │
│ stake × active)│ │ stake × m) │
└─────────────────┘ └─────────────┘
```
---
## Tuning
- `FeeDistributor.setSplit(nodeBps, userBps, keeperBps)` — owner only, sum must = 10000, each field can change ≤ 500 bps per update.
- `FeeDistributor.setSinks(...)` — swap staking contracts if upgrading.
- `GitlawbBounty.setProtocolFee(bps)` — fee cap 1000 bps (10%).
Any change is observable on-chain before it takes effect — integrators watch events.