Несколько лет назад, когда Decentraland запустила LAND, координаты парцелей хранились в одном контракте. Современные метавселенные требуют гибких решений: on-chain аренда, аукционы, adjacency premium. Мы создаём торговые площадки для виртуальной недвижимости, которые поддерживают Decentraland LAND, Sandbox LAND, Otherside Otherdeed и собственные L2-решения. Каждый проект нуждается в собственной площадке для вторичной торговли, аренды и застройки. Разработка маркетплейса виртуальной недвижимости — это пересечение инфраструктуры NFT marketplace, on-chain rental механик и spatial data management. Наш опыт включает более 5 проектов в этой области, и мы гарантируем аудит смарт-контрактов.
Техническая специфика по сравнению с generic NFT marketplace: парцели имеют координаты (x, y), возможно соседство и adjacency бонусы, аренда временная с возвратом прав, застройка создаёт metadata relationship между LAND NFT и content NFT. Эти нюансы требуют нестандартных решений: от coordinate-based tokenId до временного делегирования прав через ERC-4907.
Как работает on-chain аренда виртуальной недвижимости?
ERC-4907: Rentable NFT стандарт
Аренда виртуальной недвижимости — значимый use case: владелец хранит LAND как инвестицию, арендатор использует для застройки/мероприятий. Необходимо разделить ownership (NFT у владельца) и usage rights (у арендатора). ERC-4907 добавляет роль user к ERC-721 — временный пользователь с expiry timestamp. Контракты могут проверять userOf(tokenId) вместо ownerOf для доступа.
contract RentalMarketplace { struct RentalOffer { uint256 tokenId; address landContract; uint256 pricePerDay; uint256 minDays; uint256 maxDays; address paymentToken; // ERC-20 или address(0) для native bool active; } mapping(bytes32 => RentalOffer) public rentalOffers; function createRentalOffer( uint256 tokenId, address landContract, uint256 pricePerDay, uint256 minDays, uint256 maxDays, address paymentToken ) external { require(IERC721(landContract).ownerOf(tokenId) == msg.sender, "Not owner"); bytes32 offerId = keccak256(abi.encode(tokenId, landContract, msg.sender, block.timestamp)); rentalOffers[offerId] = RentalOffer({ tokenId: tokenId, landContract: landContract, pricePerDay: pricePerDay, minDays: minDays, maxDays: maxDays, paymentToken: paymentToken, active: true }); } function rent(bytes32 offerId, uint256 days) external payable { RentalOffer storage offer = rentalOffers[offerId]; require(offer.active, "Offer not active"); require(days >= offer.minDays && days <= offer.maxDays, "Invalid duration"); uint256 totalCost = offer.pricePerDay * days; uint256 expiry = block.timestamp + days * 1 days; // Оплата if (offer.paymentToken == address(0)) { require(msg.value >= totalCost, "Insufficient payment"); } else { IERC20(offer.paymentToken).safeTransferFrom(msg.sender, address(this), totalCost); } // Устанавливаем user через ERC-4907 IERC4907(offer.landContract).setUser(offer.tokenId, msg.sender, uint64(expiry)); // Выплачиваем владельцу (minus protocol fee) uint256 fee = totalCost * PROTOCOL_FEE_BPS / 10000; _transferPayment(offer.paymentToken, IERC721(offer.landContract).ownerOf(offer.tokenId), totalCost - fee); emit Rented(offerId, msg.sender, days, expiry); } } Collateral rental (без ERC-4907)
Если LAND контракт не поддерживает ERC-4907: временная передача NFT с collateral. Арендатор вносит залог (равный или больше стоимости LAND), NFT передаётся, по окончании — автоматический возврат через keeper или manual claim. Проблема: арендодатель теряет физическое владение NFT на время аренды (хотя имеет право вернуть). Риск: арендатор продаёт NFT несмотря на collateral. Решение: NFT передаётся в escrow контракт, не арендатору.
Какие механики marketplace необходимы?
Listing и аукционы
enum SaleType { FIXED_PRICE, ENGLISH_AUCTION, DUTCH_AUCTION } struct Listing { uint256 tokenId; address seller; SaleType saleType; address paymentToken; uint256 startPrice; uint256 endPrice; // для Dutch auction: конечная цена uint256 startTime; uint256 endTime; uint256 highestBid; // для English auction address highestBidder; } Dutch Auction особенно релевантен для первичной продажи LAND: цена начинается высоко, автоматически снижается до резервной. Устраняет газовую войну при mint — сравнение: Dutch auction снижает комиссии на 40% по сравнению с fixed-price mint.
English Auction для вторичного рынка редких Estate: бидинг с outbid защитой (минимальное повышение ставки на X%).
Royalties и fee структура
ERC-2981 для on-chain royalties. Стандартная структура маркетплейса виртуальной недвижимости:
| Fee | Получатель | Размер |
|---|---|---|
| Marketplace fee | Protocol treasury | 2-2.5% |
| Creator royalty | Оригинальный создатель метавселенной | 2.5-5% |
| Referral | Если есть referral program | 0.5-1% |
| Seller | Владелец LAND | Остаток |
Royalties для виртуальной недвижимости — контроверсиальная тема. Платформы типа Blur подорвали enforcement. Решение: royalties enforcement через контракт (не зависит от marketplace), или royalty-free модель с revenue sharing другого типа.
Что такое adjacency premium?
Уникальная черта земельных маркетплейсов: соседние парцели стоят больше вместе, чем порознь. Алгоритм поиска adjacency проверяет координаты на смежность по кардинальным и диагональным направлениям. Frontend отображает на карте выделенные смежные лоты при hover на один — пользователь видит потенциальные bundle покупки. Типичная премия за формирование estate составляет 15-30% от суммы отдельных участков. Например, два соседних участка по отдельности стоят 10 ETH каждый, а при объединении в estate их суммарная цена — 23 ETH вместо 20, то есть премия 3 ETH (15%).
LAND NFT: специфика данных
Coordinate system on-chain
Каждый парцель — NFT с координатами в сетке. Стандартный подход: tokenId кодирует координаты.
contract VirtualLand is ERC721 { struct Parcel { int256 x; int256 y; address tenant; // текущий арендатор (если сдан) uint256 leaseExpiry; // timestamp окончания аренды string contentURI; // что построено на участке uint8 zoneType; // 0=residential, 1=commercial, 2=plaza } mapping(uint256 => Parcel) public parcels; mapping(int256 => mapping(int256 => uint256)) public coordToTokenId; // coordToTokenId[x][y] = tokenId int256 public constant GRID_MIN = -150; int256 public constant GRID_MAX = 150; // tokenId = уникальный индекс из координат function coordsToTokenId(int256 x, int256 y) public pure returns (uint256) { // Сдвигаем в неотрицательные значения uint256 ux = uint256(x - GRID_MIN); uint256 uy = uint256(y - GRID_MIN); uint256 size = uint256(GRID_MAX - GRID_MIN + 1); return ux * size + uy; } function tokenIdToCoords(uint256 tokenId) public pure returns (int256 x, int256 y) { uint256 size = uint256(GRID_MAX - GRID_MIN + 1); x = int256(tokenId / size) + GRID_MIN; y = int256(tokenId % size) + GRID_MIN; } } Estate: объединённые парцели
Estate = несколько смежных парцелей, объединённых в один актив. Это значимо: большой застроенный участок ценнее суммы частей. Механика:
contract EstateRegistry is ERC721 { struct Estate { uint256[] parcels; // массив tokenId входящих парцелей address landContract; } mapping(uint256 => Estate) public estates; // парцель → estate (если входит в estate) mapping(uint256 => uint256) public parcelToEstate; function createEstate(uint256[] calldata parcelIds) external returns (uint256 estateId) { // Проверяем adjacency require(_areAdjacent(parcelIds), "Parcels must be adjacent"); // Проверяем ownership всех парцелей for (uint i = 0; i < parcelIds.length; i++) { require(landNft.ownerOf(parcelIds[i]) == msg.sender, "Not owner"); } estateId = ++_estateIdCounter; // Передаём парцели в escrow этого контракта for (uint i = 0; i < parcelIds.length; i++) { landNft.transferFrom(msg.sender, address(this), parcelIds[i]); parcelToEstate[parcelIds[i]] = estateId; } estates[estateId] = Estate({ parcels: parcelIds, landContract: address(landNft) }); _mint(msg.sender, estateId); } } Spatial Data и Map Interface
Интерактивная карта — основной UI площадки. Требования: отображение тысяч парцелей с цветовой кодировкой (продаётся, сдаётся, занято), плавный zoom/pan, клик на парцель → детальная информация.
WebGL и deck.gl — наиболее производительные варианты для spatial rendering тысяч объектов. deck.gl (Uber) оптимизирован для геоданных и работает с WebGL.
import { DeckGL } from '@deck.gl/react' import { ScatterplotLayer } from '@deck.gl/layers' const parcelLayer = new ScatterplotLayer({ data: parcels, getPosition: (d) => [d.x * PARCEL_SIZE, d.y * PARCEL_SIZE, 0], getFillColor: (d) => { if (d.forSale) return [0, 200, 100] // зелёный — на продаже if (d.forRent) return [0, 100, 200] // синий — в аренду if (d.hasContent) return [150, 100, 200] // фиолетовый — застроен return [100, 100, 100] // серый — пусто }, getRadius: PARCEL_SIZE / 2, pickable: true, onClick: ({ object }) => setSelectedParcel(object), }) Content Layer: что строят на LAND
Застройка LAND — отдельный слой данных. Стандартные форматы: Decentraland SDK scene (Babylon.js-based), GLTF/GLB assets, iframe-based content. Content URI хранится в LAND NFT metadata. При изменении застройки владелец обновляет contentURI через setContentURI(tokenId, newURI). Это on-chain транзакция, история изменений сохраняется.
Аналитика и price discovery
Площадка без аналитики — не конкурентоспособна. Необходимый минимум: floor price по зонам, price history, volume, heatmap активности, rental yield calculator. Данные индексируются через The Graph subgraph для on-chain событий и PostgreSQL с PostGIS для off-chain метаданных и пространственных запросов.
Как создать маркетплейс виртуальной недвижимости: пошаговое руководство
- Product design (1-2 недели). Карта мира, зонирование, модель первичной продажи, rental модель, fee структура.
- Смарт-контракты (4-6 недель). LAND NFT, Estate контракт, Rental marketplace, Sale marketplace. Обязательный аудит.
- Backend и indexer (3-4 недели). Subgraph, REST/GraphQL API, spatial queries, price analytics.
- Map Frontend (4-6 недель). Интерактивная карта, parcel detail page, listing/rental UI, analytics dashboard.
- 3D Content preview (2-3 недели, опционально). GLTF preview для застроенных парцелей.
- Тестирование и launch. End-to-end тест, нагрузочный тест карты.
MVP без Estate и 3D content займёт 3-4 месяца. Полная версия с Estate, rental, аналитикой и 3D preview — 6-8 месяцев.
Стек разработки
| Компонент | Технология |
|---|---|
| LAND NFT | Solidity ERC-721 + ERC-4907 |
| Estate контракт | Solidity с adjacency validation |
| Rental контракт | Solidity + ERC-4907 |
| Marketplace контракт | Solidity + ERC-2981 |
| Indexer | The Graph (subgraph) |
| Spatial DB | PostgreSQL + PostGIS |
| Map frontend | deck.gl / Mapbox GL JS + React |
| 3D preview | Three.js / Babylon.js |
| Backend API | Node.js + Fastify |
| Storage | IPFS (Pinata) + Arweave |
Закажите разработку под ключ — наши инженеры с опытом более 5 лет в blockchain оценят ваш проект и предложат оптимальное решение.
Что входит в работу
- Разработка и аудит смарт-контрактов (Solidity, Foundry)
- Интеграция с The Graph для индексации
- Реализация интерактивной карты (deck.gl)
- Backend API и база данных (PostgreSQL + PostGIS)
- Документация по интеграции и деплою
- Техническая поддержка в течение 1 месяца после запуска
Получите консультацию по разработке маркетплейса виртуальной недвижимости. Владельцы LAND экономят до 30% при bundle-продаже благодаря adjacency premium.







