Maintenance, Yield, and Redistribution
GDA-based resource maintenance, on-chain local bonus, UBI pool, and bitmap-dispute Harberger buyout.
Maintenance, Yield, and Redistribution
Maintenance — GDA model
Maintenance is paid in resources via Superfluid's General Distribution Agreement (GDA). The player's PlayerProxy is the GDA admin; each tile they hold a licence for is a pool member receiving resource tokens.
Maintenance funding is open and additive. Any address may stream valid resources toward a tile's upkeep. No registration or approval step is required for contributors; multiple independent payers can support the same tile at once.
Each tile registers up to 3 resource tokens as maintenance sources. Registration stores a TaxEntry permanently in the tile's instance contract:
struct TaxEntry {
address resourceToken;
uint8 rarityTier; // 0=Common … 3=Legendary; cached from token
uint256 sourceTileId; // tile that mines this resource
uint16 localBonusBps; // 200 / 150 / 125 / 112 / 100 for rings 0–3+
}
At registration the contract verifies MiningRegistry.isMined(token, sourceTileId) — mining is a permanent on-chain state, so entries never go stale. The hex distance between source tile and paying tile is computed once and localBonusBps is cached permanently.
The local bonus is geographic, not licence-based: it applies regardless of who currently holds the licence on the source tile. This incentivises commerce — buying resources from nearby tiles is more maintenance-efficient even after those licences change hands.
Default cascade: closing the player's GDA flow to zero cuts all tile pool members simultaneously. A defaulting player's entire maintenance position collapses in a single liquidation call, regardless of how many licences they hold.
Declared value
Each tile's declared value determines both its acquisition cost and the tile's share of USDCx yield.
Yield routing is intentionally simple:
- if the tile has a configured
beneficiary, outbound value goes there - otherwise, outbound value goes to the current tile owner
Maintenance contributors do not automatically gain control rights or payout rights by funding upkeep; delegation and higher-level agreements live above the base protocol.
Declared value is computed from the aggregate live maintenance state, regardless of which addresses are paying:
totalTaxWeight = Σ (memberFlowRate_i × RARITY_MULT[tier_i] × localBonusBps_i / 100)
RARITY_MULT = [1, 3, 9, 18] (Common, Uncommon, Rare, Legendary)
Local bonus by ring distance between source tile and paying tile:
| Ring | Bonus | |------|-------| | 0 (same tile) | ×2.00 | | 1 | ×1.50 | | 2 | ×1.25 | | 3 | ×1.12 | | 4+ | ×1.00 (no bonus) |
Combined effect: a same-tile Legendary resource is worth 36× a no-bonus Common resource (18 × 2 = 36).
Neighborhood context and acquisition cost
Each tile's acquisition cost reflects how many of its 3-ring neighbors (up to 36 tiles) are licensed to the same player versus foreign players.
effectiveDays = max(9, 54
− foreignNeighbors × 2.5
+ ownNeighbors × 1.0)
| Context | Effect | |---------|--------| | More same-licensee neighbors | higher effectiveDays → more expensive to acquire | | More foreign-licensee neighbors | lower effectiveDays → cheaper to acquire | | True frontier (few neighbors) | low base rate, low cost | | Fully surrounded by foreign licences (18 foreign) | floor: 9 days | | Fully self-licensed 2-ring (18 own) | ceil: 72 days |
Acquisition cost: totalTaxWeight(tile) × effectiveDays × 86400
Harberger — bitmap claim
The claimant submits an offer alongside a 36-bit neighbor bitmap (uint64) encoding which of the 36 neighbors (3 rings) they claim are foreign-owned. The contract records the claim and computes effectiveDays from it — no on-chain neighbor verification at offer time.
struct BuyoutOffer {
uint256 tileId;
uint256 offerAmount; // stated offer; 10% is escrowed as deposit
uint64 neighborBitmap; // 36 bits: bit i = 1 → neighbor i is foreign-licensed
uint48 submittedAt; // block.timestamp at submission
}
Claims must be above the current buyout price. Any higher live claim supersedes the previous one, and the previous claimant's 10% deposit is returned as credit.
Response window: 24 hours from the most recent claim.
- Offer: claimant posts only 10% of the stated offer as deposit.
- Accept: the contract pulls the remaining 90% from the claimant. If the pull succeeds, the seller receives the full stated offer and the licence transfers via
TileHarberger.settle(). If the pull fails, the claimant's 10% deposit is burned, the offer clears, and the current owner keeps the tile. - Refuse: the owner burns 10% of the offer amount as the penalty. Licence stays. The owner or their delegates may adjust maintenance immediately after refusing — the new rate takes effect for any subsequent claim.
Defaulting licensees: if a licensee stops paying maintenance, totalTaxWeight → 0 and acquisition cost → floor. Any player can file a claim above that floor. A higher live claim replaces a lower claim.
Dispute (permissionless)
Any address can call dispute(offerId, bitIndex) during the 24-hour window, pointing to a specific bit they claim is wrong.
The contract looks up the actual tile at that bitmap index and checks on-chain ownership:
| Dispute result | Consequence |
|---|---|
| Bitmap wrong; licence unchanged since claim | Disputer receives the posted deposit, capped by the 20% bounty formula; claim cancelled |
| Bitmap wrong; licence changed after submittedAt | Posted deposit returned to claimant; claim cancelled; no penalty (good-faith escape hatch) |
| Bitmap correct | No action; claim remains live |
The escape hatch relies on ownershipLastChanged[tileId] — a timestamp updated in _settle() on every licence transfer. Claimants who submitted an honest bitmap are protected from being slashed for state changes that happen during the response window.
Incentive: the 20% bounty makes monitoring claims economically rational for keeper bots, making the dispute surface self-policing without requiring active participation from the licensee.
Base redistribution — 7-day smooth GDA
A global GDA pool distributes USDCx continuously to all maintenance-paying players.
Rate: treasuryBalance / 7 days, recalculated on every treasury deposit (auction proceeds, patent Harberger inflow). Fully programmatic — no admin action or governance required. If inflows stop entirely, the pool runs dry in one week.
Units: each player's units in the UBI pool equal their totalTaxWeight (declared value) summed across all tiles. Units are updated in the same transaction as any maintenance stream change — there is no lag.
Self-reinforcing loop:
- Auctions → treasury → UBI stream → players
- UBI makes productive licences valuable → higher auction bids
- Higher bids → larger treasury → higher UBI rate
- Higher rate → resources more valuable → more acquisition activity
Faction crown stream
The maintenance dividend is not the whole political layer.
Separately from the global redistribution pool, the protocol may run a single faction victory CFA:
- it is active only while one faction controls the full outer crown
- it flows to the faction treasury, not directly to individuals
- it ends the moment the crown condition breaks
This is the main winner/loser signal in the economy. The global maintenance dividend keeps the baseline game alive; the crown stream makes temporary hegemony materially meaningful.
Anti-stagnation
Maintenance is a live recurring commitment, not a one-time cost.
- Stopping payments → declared value drops to zero → UBI share collapses immediately
- Non-payment exposes licences to cheap Harberger claims (acquisition cost floor = 1 day output)
- Paying higher maintenance earns proportionally more UBI stream — and signals a productive licence, potentially attracting claimants
- A defaulting player's entire position liquidates in a single stream closure call
Reasoning trace
- Keeping the base redistribution pool avoids a pure runaway-king system where the first winner starves everyone else immediately.
- Adding a separate crown stream introduces visible political asymmetry without deleting the underlying economic sandbox.
- Routing the asymmetric reward to faction treasury instead of wallets makes alliances financially real.