Cost Model

Pricing of compute leases

[!WARNING] Work in progress The rates and constants on this page are placeholder values for development and testing. Final pricing, rate ratios, and economic parameters are still under design review and will change before production.

Lease pricing is fully deterministic. The cost is computed from the resource dimensions and duration using integer arithmetic with milli-XUSD precision. The ledger validates that every lease block carries the exact cost produced by this formula -- no negotiation, no rounding errors.

Formula

The cost is calculated in two steps: a per-hour rate in milli-XUSD, then converted to whole XUSD:

perHourMilli = vCPUs x 20 + ceil(memoryMB / 1024) x 10 + diskGB x 1
hours        = ceil(duration / 3600)
costMilli    = perHourMilli x hours
cost         = ceil(costMilli / 1000)     // minimum 1

In Go:

func LeaseCost(vcpus, memoryMB, diskGB, duration uint64) (uint64, error) {
    hours := (duration + 3599) / 3600
    memGB := (memoryMB + 1023) / 1024
    perHourMilli := vcpus*LeaseVCPURate + memGB*LeaseMemGBRate + diskGB*LeaseDiskGBRate
    costMilli := perHourMilli * hours  // overflow-checked via safeMul
    cost := (costMilli + 999) / 1000   // ceiling divide
    if cost == 0 { cost = 1 }
    return cost, nil
}

Rate table

Resource

Rate

Unit

vCPU

20 milli-XUSD

per vCPU per hour

Memory

10 milli-XUSD

per GB per hour (rounded up to nearest GB)

Disk

1 milli-XUSD

per GB per hour

[!NOTE] Rounding Memory is rounded up to the nearest GB: 1025 MB counts as 2 GB. Duration is rounded up to the nearest hour: 3601 seconds counts as 2 hours. Cost in milli-XUSD is rounded up to the nearest whole XUSD. All rounding uses integer ceiling division.

Derived values

Value

Formula

Description

Cost

See above

XUSD debited from consumer

Stake

cost / 5 (min 1)

XUSD locked by provider as collateral

XE Reward

Same as cost formula

XE emitted to provider on settlement

The stake uses integer division: a cost of 7 yields a stake of 1 (7/5 = 1 in integer arithmetic). The minimum stake is 1 XUSD regardless of cost.

Constants

const (
    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
    LeaseMinDuration  = 60       // minimum 1 minute
    LeaseMaxDuration  = 31536000 // maximum 365 days
)

Examples

vCPUs

Memory

Disk

Duration

Per-Hr Milli

Hours

Cost Milli

Cost (XUSD)

Stake

1

1024 MB

1 GB

60s

20+10+1=31

1

31

1

1

1

512 MB

5 GB

120s

20+10+5=35

1

35

1

1

2

2048 MB

20 GB

3600s

40+20+20=80

1

80

1

1

4

8192 MB

100 GB

3600s

80+80+100=260

1

260

1

1

2

4096 MB

50 GB

86400s

40+40+50=130

24

3120

4

1

8

16384 MB

200 GB

86400s

160+160+200=520

24

12480

13

2

4

8192 MB

100 GB

2592000s

80+80+100=260

720

187200

188

37

[!EXAMPLE] Worked example: 2 vCPUs, 4 GB RAM, 50 GB disk for 24 hours

Per-hour milli = (2 x 20) + ceil(4096/1024) x 10 + 50 x 1
               = 40 + 40 + 50
               = 130 milli-XUSD/hour

Hours          = ceil(86400 / 3600) = 24

Cost milli     = 130 x 24 = 3120

Cost           = ceil(3120 / 1000) = 4 XUSD
Stake          = 4 / 5 = 0 → min 1 = 1 XUSD
XE Reward      = 4 XE (on settlement)

Validation

The ledger enforces the following invariants:

Check

Rule

Cost matches formula

block.Amount == LeaseCost(vcpus, memoryMB, diskGB, duration)

Stake matches formula

lease_accept.Amount == cost / LeaseStakeDivisor (min 1)

XE reward matches formula

lease_settle.Amount == LeaseCost(vcpus, memoryMB, diskGB, duration)

Duration in range

60 <= duration <= 31,536,000 seconds

Resources non-zero

At least one resource dimension must be > 0

No overflow

Multiplication uses safeMul() with overflow detection via bits.Mul64

Integer arithmetic

All calculations use uint64 -- no floating point

[!WARNING] Overflow protection The cost calculation uses bits.Mul64 to detect overflow. If perHourMilli * hours would exceed uint64 max, the lease is rejected. This prevents absurdly large resource requests from wrapping around.