Skip to main content

How It Works — Technical

For the plain-language version, see Basics → How It Works.

You draw a shape. The protocol checks it against every existing parcel, charges for the area, and records it as yours. From that moment, anyone can take it at the current price — one transaction, no signature from you.

The protocol rests on two guarantees:

  • No two parcels ever overlap. On-chain validation uses exact integer math — fixed-point SAT, no floats, no tolerance.
  • Every parcel is always for sale. The market holds a capability that moves ownership without the current owner signing.

This page shows how each guarantee is enforced. The full specification lives in the Yellowpaper.


Two Layers

The protocol ships as two Move packages with a clean separation of concerns.

mercatr is the spatial engine: geometry, collision detection, the on-chain index. It stores parcel shapes, validates them, and runs the overlap check. It knows nothing about money.

mercatr_market layers money on top. It prices every registration and buyout, collects payment, and routes splits to the treasury and the hierarchy pool.

The market holds two capabilities issued by the spatial engine:

  • LifecycleCap authorizes register, remove, transfer_ownership, and market-mediated geometry mutations (expand, rebalance, split, merge). Any operation that changes what parcels exist or how they're shaped requires a valid LifecycleCap.
  • TransferCap authorizes force_transfer — the specific call that flips ownership without the current owner's signature. Only forced buyouts use this path.

Capabilities keep the spatial core auditable. Indexers, games, and secondary markets can read mercatr without trusting pricing logic; governance upgrades to mercatr_market cannot silently alter stored geometry.


The Shared Index

Every cadastral level has one shared Index object on-chain. Every registration, buyout, and removal reads and writes it.

Index fields
FieldTypePurpose
cellsTable<u64, vector<ID>>Morton code → list of polygon IDs in that cell
polygonsTable<ID, Polygon>polygon ID → full stored geometry, owner, AABB
occupied_depthsu32bitmask of quadtree depths that have at least one polygon
authorized_capsVecSet<ID>set of cap object IDs currently authorized to act on this index
authorization_sealedboolwhen true, no new caps can be minted or authorized

Index is a Sui shared object, so many users touch it concurrently. Every registration runs inside a Programmable Transaction Block, so the overlap check and the insert commit as one atomic step. No transaction can squeeze between "check passed" and "parcel inserted" — Sui's object locking serializes writers on the shared Index.

LevelTypical useLevel rate RR
0–5Continental, national claimslowest
6–12Regional, citymid
13–20Neighbourhood, building footprinthighest

See Key Concepts → Spatial Hierarchy for the quadtree model and Morton-code addressing.


Capability Model

The Index enforces a strict authorization model. Every write operation checks that the capability object presented is in the index's authorized_caps set. A cap not in that set is rejected with ECapRevoked, even if the object itself is valid.

Authorization lifecycle:

  1. Mint. mint_transfer_cap or mint_lifecycle_cap creates a new cap and inserts its ID into authorized_caps. Both calls abort if authorization_sealed is true.
  2. Cross-authorize. A cap minted on one index can be authorized on peer indexes via authorize_cap. This lets a single cap pair act across all cadastral levels. Cross-authorization also aborts on a sealed index.
  3. Revoke. revoke_cap removes a cap ID from authorized_caps. Revocation works even on a sealed index — it's a safety operation. After revocation, the cap object still exists but every call using it aborts.
  4. Seal. seal_index sets authorization_sealed = true. A sealed index rejects all new minting and authorization. Unsealing is only valid transiently inside a cap-rotation PTB; the PTB must reseal before it ends. If any step aborts, the whole PTB rolls back and the index stays sealed.
info

Cap rotation during upgrades follows a strict sequence: unseal → mint new caps → cross-authorize on peer indexes → swap into market → revoke old caps → reseal. The old cap objects remain in the multisig as an audit trail but are inert after revocation.


Registering a Parcel

Registration compiles a shape into an owned, indexed parcel in one atomic transaction. Naming the parcel — setting its metadata — is a separate transaction after registration.

  1. Draw. The app decomposes your shape into up to 10 convex parts. The protocol accepts only convex geometry, which keeps SAT exact and cheap. See Geometry Rules.
  2. Validate. Vertex count, positive area, minimum edge length, convexity of every part, connectivity of parts, compactness ratio. Any failure reverts the entire PTB.
  3. Spatial lookup. Compute the AABB, pick the natural quadtree depth (shallowest level where the AABB fits one cell), and gather candidate parcel IDs from every cell the AABB touches.
  4. Collision check. Three phases — see the next section.
  5. Insert. The parcel enters cells and polygons. A Registered event fires.
  6. Pay and seed premium. The market charges the registration price, splits payment, assigns ownership, and seeds premium_ppm to the first resale rung (2_950_000, i.e. 2.95×).

Registration is atomic: a valid parcel or nothing. Funds never spend partially.

warning

A failed transaction still costs gas. Sui charges gas for any transaction that reaches the execution engine, whether it succeeds or reverts. Geometry validation failures, overlap rejections, and payment shortfalls all consume gas.

The registration price is the area times the level rate:

Pregister=A×R106P_{\text{register}} = A \times \frac{R}{10^6}

where AA is the polygon area in m² and RR is the level rate in mist per m² scaled by 10610^6.

Natural depth comes from the AABB — you cannot ask for a deeper or shallower cell. A parcel that straddles a cell boundary rises to the nearest ancestor that contains it whole.

Registration creates the parcel only. The parcel has no name or visual layer until you call set_metadata in a separate transaction.

See Register Land for the app walkthrough.


Three-Phase Collision

The overlap check gets faster and more precise at each phase. Expensive work runs only on the few candidates that survive the cheap filters.

Broadphase — depth/cell scan with probe budget. The broadphase reads occupied_depths (a bitmask) to skip empty quadtree levels entirely, then walks the cells the new parcel's AABB touches at each occupied depth. Candidate parcel IDs accumulate up to a probe budget. Morton-code addressing makes each cell lookup a single Table read. The search is bounded by the probe budget, not by total parcel count.

Midphase — O(k)O(k). AABB-vs-AABB test on each of the kk candidates. Non-touching boxes drop out with a few integer comparisons.

Narrowphase — O(kp2)O(k \cdot p^2) with tiny constants. Separating Axis Theorem on every surviving part-pair, in fixed-point integer arithmetic — no floats, no tolerance, no rounding. Shared boundary edges and single-point touches pass. Any positive shared area aborts with EOverlap. With the 10-parts limit, p2100p^2 \le 100 in the worst case.

info

Touching is allowed. Two parcels can share a boundary edge or a corner vertex — the protocol distinguishes zero shared area from positive shared area with exact integer math. No epsilon tolerances.

Complexity with realistic constants

In practice kk is small (single digits) because the natural depth pins the search to a tight cell neighbourhood. The occupied_depths bitmask prunes empty levels before any table lookup. Midphase rejects most candidates on a single integer compare. Narrowphase is bounded by the product of parts, capped at 10 × 10 = 100 part-pairs, and each pair costs a fixed SAT budget: project onto each edge normal, compare min/max, done. The whole pipeline fits comfortably inside a single Sui transaction's compute budget even at maximum depth.


The Spatial Guarantee

Two parcels never overlap. The protocol rejects the second one.

The overlap check and the insert run inside the same PTB. Either the full pipeline succeeds, or the transaction reverts and nothing changes. No "pending" phase exists for a second transaction to exploit.

No setting turns this off. Every registration at every level runs the full pipeline. Contracts built on merca.earth never arbitrate boundary disputes — the protocol already did.


Buying a Parcel

Every parcel is always for sale. Owners cannot refuse. This is the Harberger property.

The buyout price:

Pbuyout=A×R106×M106P_{\text{buyout}} = A \times \frac{R}{10^6} \times \frac{M}{10^6}

where AA is area in m², RR is the level rate, and MM is the parcel's current premium multiplier (stored as premium_ppm).

A buyout runs in one PTB, reassigning ownership in the same step that collects payment:

  1. Pay. The buyer covers the full buyout price in a single Coin<SUI> input.
  2. Split. 85% to the seller, 7% to treasury, 8% to the hierarchy pool. See Hierarchy Pool.
  3. Transfer. The market calls index::force_transfer with its TransferCap. The parcel's owner field flips. No signature from the previous owner. This is the only path where TransferCap is used — ordinary market operations (register, remove, geometry mutations) use LifecycleCap instead.
  4. Advance. premium_ppm advances one rung on the resale ladder. It does not reset for the new owner. See The Resale Ladder.

The capability design keeps forced transfer safe. Only the market contract holds TransferCap, and it uses it only inside a PTB that verifies payment and routes splits.

warning

A buyout completes or reverts in full. If someone else bought the parcel an instant earlier, your transaction reverts — you pay gas but keep your funds. The price you quoted may already be stale. Quote the price fresh inside the same PTB.

danger

Forced transfer is irreversible. No grace period, no cool-down, no recourse. Once force_transfer executes, ownership is gone. Defend parcels you care about by keeping liquidity on hand to buy back, or by using the owner price controls to move your premium up or down — see Bump Price and Drop Price.

See Buying a Parcel for the app walkthrough, and Hierarchy for how the 8% cascades up parent levels.


Where to Go Next