Lease Economics¶
Design decisions pending. The current pricing model is a placeholder — flat resource rates with no performance weighting. The target model introduces a performance-based value coefficient. See Future: Performance-Based Pricing for the planned direction.
Current Model (v0.4.0)¶
Overview¶
Lease pricing is deterministic and computed on-chain from three resource dimensions (vCPUs, memory, disk) and duration. All nodes independently compute the same cost and reject blocks that don't match. There is no negotiation on price — the formula is a protocol constant.
The same formula (LeaseCost) is used for both XUSD cost and XE emission, meaning the provider earns exactly as much XE as the consumer spends in XUSD.
Constants¶
Defined in core/ledger.go:
| Constant | Value | Unit |
|---|---|---|
LeaseVCPURate |
20 | milli-XUSD per vCPU per hour |
LeaseMemGBRate |
10 | milli-XUSD per GB memory per hour |
LeaseDiskGBRate |
1 | milli-XUSD per GB disk per hour |
LeaseStakeDivisor |
5 | stake = cost / 5, minimum 1 |
LeaseMinDuration |
60 | seconds |
LeaseMaxDuration |
31,536,000 | seconds (365 days) |
Cost Calculation¶
hours = ceil(duration_seconds / 3600)
memGB = ceil(memory_mb / 1024)
perHourMilli = (vcpus × 20) + (memGB × 10) + (diskGB × 1)
costMilli = perHourMilli × hours
cost = max(1, ceil(costMilli / 1000))
The intermediate calculation is in milli-XUSD to avoid floating point. The final cost is ceiling-divided to whole XUSD with a minimum of 1.
Example: 2 vCPUs, 2048 MB memory, 10 GB disk, 3600 seconds (1 hour): - perHourMilli = (2×20) + (2×10) + (10×1) = 40 + 20 + 10 = 70 - costMilli = 70 × 1 = 70 - cost = ceil(70 / 1000) = 1 XUSD
Example: 4 vCPUs, 8192 MB memory, 100 GB disk, 720 hours (30 days): - perHourMilli = (4×20) + (8×10) + (100×1) = 80 + 80 + 100 = 260 - costMilli = 260 × 720 = 187,200 - cost = ceil(187,200 / 1000) = 188 XUSD
Denomination¶
All on-chain amounts are unsigned 64-bit integers. There are no fractional tokens.
| Token | On-chain representation | Notes |
|---|---|---|
| XUSD | Integer count (uint64) | Payment token, burned on lease |
| XE | Integer count (uint64) | Emission token, minted on settlement |
Money Flow¶
Consumer Provider
──────── ────────
lease block
XUSD balance -= cost ─────────────────► (pending send created)
lease_accept block
◄───────────────────── XUSD balance -= stake
(pending send deleted = consumer XUSD burned)
lease_settle block
◄───────────────────── XE balance += emission (minted)
XUSD balance += stake (returned)
Consumer: Pays cost XUSD. This XUSD is permanently burned (deleted from pending sends on acceptance). The consumer receives compute access for the lease duration.
Provider: Stakes cost / 5 XUSD upfront on acceptance. On settlement after the lease expires, the stake is returned and emission XE is minted. The provider earns XE from nothing — it is newly created supply.
Net effect: XUSD is deflationary (burned on every lease). XE is inflationary (minted on every settlement). The two tokens serve different purposes: XUSD for payment and voting weight, XE for economic incentive.
Stake¶
The provider must lock cost / LeaseStakeDivisor (cost ÷ 5, minimum 1) XUSD when accepting a lease. This creates a disincentive against accepting leases without providing compute — the stake is only returned on valid settlement after the lease duration expires.
Known issue (core#113): A provider can grief consumers by accepting a lease (burning consumer XUSD) and never settling, losing only their stake. The griefing ratio is 5:1 (consumer loses 5× what the provider loses). This needs an escrow or forced-settlement mechanism.
Attestations (Timestamps)¶
Both lease_accept and lease_settle blocks require timekeeper attestations — signed timestamps from trusted third parties. This prevents providers from faking timestamps to settle early.
- Minimum attestations: configurable threshold (from
TimekeeperConfig) - Maximum per block: 20
- Maximum skew: ±10 minutes from current time
- Settlement check: attested timestamp must be ≥
startTime + duration(in nanoseconds)
Known issue (core#44): For short leases (under 1 hour), the 10-minute attestation skew window can allow effectively instant settlement. Needs design review.
Where the Code Lives¶
| Component | File | Key Lines |
|---|---|---|
| Constants | core/ledger.go |
59-67 |
LeaseCost() |
core/ledger.go |
31-50 |
safeMul() (overflow check) |
core/ledger.go |
52-57 |
| Lease block validation | core/ledger.go |
638-711 |
| Lease accept validation (stake) | core/ledger.go |
713-819 |
| Lease settle validation (emission) | core/ledger.go |
821-910 |
| Stake return in balance rebuild | core/ledger.go |
250-266 |
| Marketplace offer with cost | node/node.go |
850-895 |
| Consumer lease block creation | node/node.go |
1210-1242 |
| Attestation validation | core/attestation.go |
62-113 |
Problems with the Current Model¶
1. No performance differentiation¶
All vCPUs are priced identically. A provider running a high-end server with fast NVMe and a provider running a Raspberry Pi charge the same rate. There is no incentive to provide quality compute.
2. Fixed rates are protocol constants¶
The rates (20/10/1 milli-XUSD) are hardcoded. Changing them requires a protocol update across all nodes. There is no market-driven price discovery.
3. XE emission mirrors XUSD cost exactly¶
The emission formula is identical to the cost formula. There is no independent lever to control token supply pressure. If costs go up (to reflect quality), emissions go up proportionally — which may not be desirable.
4. No accountability for uptime or quality¶
The provider earns the full emission regardless of actual compute quality, uptime, or availability during the lease. The only check is that enough time passed.
5. Griefing ratio¶
The 5:1 stake ratio means a malicious provider can burn $5 of consumer value for every $1 they risk. This is too favourable for attackers.
Future: Performance-Based Pricing¶
The target model replaces flat resource rates with a performance-derived value:
performance_score × time = lifetime_value
xusd_cost = lifetime_value × cost_coefficient
xe_emission = lifetime_value × emission_coefficient
Performance Score¶
The performance score captures the actual capability of the resources being leased, not just their nominal specification. A 4-vCPU machine with fast cores on NVMe storage should score higher than 4 vCPUs on a slow host.
Open questions:
- How is performance measured? Options include:
- Benchmark on provision (run a standard benchmark suite when the VM starts)
- Self-reported by provider (requires verification mechanism)
- Measured by consumer workload (too variable, hard to standardize)
-
Proof-of-uptime heartbeat with embedded micro-benchmarks
-
What dimensions contribute? At minimum:
- CPU throughput (single-core and multi-core)
- Memory bandwidth
- Disk IOPS and throughput
-
Network latency and bandwidth (to other nodes)
-
How does it compose with resources? A machine with 4 high-performance vCPUs is worth more than 4 low-performance vCPUs, but it also needs to account for memory and disk:
-
Who runs the benchmark? If the provider benchmarks themselves, they could inflate scores. If the consumer runs it, they could deflate. A neutral party (timekeeper? sentinel node?) may be needed.
-
How often is it measured? Once at provider registration? Per lease? Continuously? There's a tradeoff between accuracy and overhead.
Lifetime Value¶
This represents the total compute value delivered. A fast machine running for 1 hour has the same lifetime value as a machine half as fast running for 2 hours (assuming similar resources).
Cost and Emission Coefficients¶
Two independent coefficients decouple XUSD cost from XE emission:
- cost_coefficient: Controls how expensive compute is in XUSD. Could be a governance parameter on the state chain.
- emission_coefficient: Controls XE inflation rate independently of pricing. Could decrease over time (halving schedule, decay curve) to control long-term supply.
Open questions:
- Who sets the coefficients? Options:
- Protocol constants (like today, but with two levers)
- DAO governance via state chain
-
Market-driven (providers set prices, protocol sets emission)
-
Should cost be market-determined? Providers could set their own prices (competing on price×performance), with the protocol only governing emission rates. This would allow natural price discovery.
-
How to handle the stake? Current model stakes
cost / 5. With performance-based pricing, the stake could be tied to the performance claim — higher claimed performance requires higher stake, penalizing inflated benchmarks.
Transition Plan¶
The migration from flat rates to performance-based pricing requires:
-
Benchmarking infrastructure: A standard benchmark suite that runs on provisioned VMs and produces a reproducible score.
-
Score attestation: A mechanism to verify benchmark results (possibly integrated with proof-of-uptime heartbeats).
-
Coefficient governance: A way to set and update cost/emission coefficients (likely via state chain DAO operations).
-
Protocol versioning: Existing leases created under flat rates must still validate. New leases would use the performance model. The validation code needs to handle both.
-
Marketplace update: Resource offers would include a performance score and derived cost, not just raw resource dimensions.
Impact on Existing Components¶
| Component | Change Needed |
|---|---|
LeaseCost() |
Replace with LifetimeValue() × coefficient |
| Lease block | Add performance_score field |
| Marketplace offers | Include benchmark score |
| Provider registration | Run benchmark, publish score |
| Attestation system | Possibly attest benchmark results |
| State chain | Store coefficients as governance parameters |
| Settlement validation | Verify performance score was legitimate |
| Proof-of-uptime | Integrate micro-benchmarks into heartbeats |
| Explorer / wallet | Display performance scores and derived costs |