Ми стикалися з проєктами, де традиційні реєстри нерухомості гальмували угоди на 4–6 тижнів, а історія володіння губилася в паперових архівах. Блокчейн-реєстр власності вирішує ці проблеми: прозорий ланцюжок переходів прав, атомарні угоди (одночасна передача NFT та оплати через ескроу), фракційна власність для інвестицій та програмовані умови передачі. Такий реєстр швидший за паперовий у сотні разів — угода займає 5–15 хвилин замість тижнів. Ми реалізували 10+ проєктів, включаючи реєстри для комерційної нерухомості та токенізацію земельних ділянок. Оцінимо ваш проєкт за 24 години — зв'яжіться з нами.
Правовий контекст: перша складність
Ключове обмеження: у більшості юрисдикцій право власності на нерухомість створюється державною реєстрацією, а не записом у блокчейні. Блокчейн-реєстр повинен або бути офіційним (державний проєкт), або працювати як Layer 2 поверх офіційного реєстру — відстежує транзакції, спрощує процес, але фінальна реєстрація в Росреєстрі/Кадастрі залишається обов'язковою.
Виняток: цифрові активи (віртуальна нерухомість у метавсесвітах, mineral rights у деяких юрисдикціях, securities-based fractional ownership).
Для реального майна — патерн "blockchain as notary": фіксуємо факти та документи, але правова сила за офіційними органами.
Як блокчейн-реєстр власності гарантує незмінність записів?
Кожен об'єкт нерухомості — унікальний NFT із метаданими (кадастровий номер, адреса, площа, документи в IPFS). Запис у блокчейні незмінний: ніхто не може підмінити історію або приховати обтяження. При передачі права перевіряються активні застави та арешти — смарт-контракт блокує транзакцію, якщо є активні обтяження. Завдяки цьому такі реєстри знижують кількість судових спорів на 80%.
contract PropertyRegistry is ERC721URIStorage, AccessControl {
bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE");
bytes32 public constant NOTARY_ROLE = keccak256("NOTARY_ROLE");
struct Property {
string cadastralNumber;
string propertyType;
string address_;
uint256 area;
bytes32 documentsHash;
uint256 registeredAt;
uint256 lastTransferAt;
bool encumbered;
string encumbranceDetails;
}
mapping(uint256 => Property) public properties;
mapping(string => uint256) public cadastralToToken;
mapping(uint256 => Lien[]) public propertyLiens;
struct Lien {
address creditor;
uint256 amount;
uint256 expiresAt;
string description;
bool active;
}
event PropertyRegistered(uint256 indexed tokenId, string cadastralNumber, address owner);
event PropertyTransferred(uint256 indexed tokenId, address from, address to, uint256 price);
event LienAdded(uint256 indexed tokenId, address creditor, uint256 amount);
function registerProperty(
address owner,
string calldata cadastralNumber,
string calldata propertyType,
string calldata address_,
uint256 area,
bytes32 documentsHash,
string calldata metadataURI
) external onlyRole(REGISTRAR_ROLE) returns (uint256 tokenId) {
require(cadastralToToken[cadastralNumber] == 0, "Already registered");
tokenId = uint256(keccak256(abi.encodePacked(cadastralNumber)));
properties[tokenId] = Property({
cadastralNumber: cadastralNumber,
propertyType: propertyType,
address_: address_,
area: area,
documentsHash: documentsHash,
registeredAt: block.timestamp,
lastTransferAt: block.timestamp,
encumbered: false,
encumbranceDetails: ""
});
cadastralToToken[cadastralNumber] = tokenId;
_safeMint(owner, tokenId);
_setTokenURI(tokenId, metadataURI);
emit PropertyRegistered(tokenId, cadastralNumber, owner);
return tokenId;
}
function addLien(
uint256 tokenId,
address creditor,
uint256 amount,
uint256 duration,
string calldata description
) external onlyRole(NOTARY_ROLE) {
propertyLiens[tokenId].push(Lien({
creditor: creditor,
amount: amount,
expiresAt: block.timestamp + duration,
description: description,
active: true
}));
properties[tokenId].encumbered = true;
emit LienAdded(tokenId, creditor, amount);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
internal override
{
super._beforeTokenTransfer(from, to, tokenId, batchSize);
if (from != address(0)) {
require(!hasActiveLiens(tokenId), "Property has active liens");
}
}
function hasActiveLiens(uint256 tokenId) public view returns (bool) {
Lien[] memory liens = propertyLiens[tokenId];
for (uint i = 0; i < liens.length; i++) {
if (liens[i].active && block.timestamp < liens[i].expiresAt) return true;
}
return false;
}
}
Чому блокчейн-реєстр швидший і безпечніший за паперовий?
| Критерій | Традиційний реєстр | Блокчейн-реєстр |
|---|---|---|
| Час угоди | 1–4 тижні | 5–15 хвилин |
| Прозорість історії | Бухгалтерські книги, ризик помилок | Повна on-chain історія |
| Безпека | Підробка підписів, рейдерські захоплення | Криптографія, мультипідписи |
| Інтернаціональність | Окремі нотаріуси, мовні бар'єри | Єдиний стандарт, атомарні угоди |
| Фракціональність | Дуже складно | Легко через ERC-20 |
Як впровадити блокчейн-реєстр: покроковий план
- Аналіз вимог — визначаємо стек (Ethereum/Polygon/BNB Chain), юридичні рамки, інтеграцію з держреєстрами.
- Проектування архітектури — обираємо стандарти (ERC-721, ERC-1155), патерни ескроу, фракціональну модель.
- Розробка смарт-контрактів — Property Registry, Escrow, Fractional Property. Використовуємо OpenZeppelin для безпеки.
- Тестування — unit-тести на Foundry, інтеграційні тести, фаззинг Echidna. Обов'язковий аудит через Slither і Mythril.
- Інтеграція з The Graph і IPFS — індексація подій, зберігання документів.
- Розгортання та навчання — деплой в обрану мережу, CI/CD, навчання команди.
Деталі безпеки
Ми використовуємо патерн Checks-Effects-Interactions, захист від реентрансі, формальну верифікацію критичних контрактів. Усі контракти проходять зовнішній аудит.Як працюють атомарні угоди в блокчейн-реєстрі?
Атомарна угода — одночасний обмін NFT на гроші без посередників. Покупець вносить кошти в ескроу-контракт, нотаріус перевіряє умови (відсутність обтяжень, повний комплект документів). Як тільки все виконано, NFT передається покупцеві, а кошти — продавцеві. Весь процес займає 5-15 хвилин і виключає ризик шахрайства.
Архітектура property registry
Property NFT
Кожен об'єкт нерухомості — унікальний NFT. Metadata містить кадастровий номер, адресу, площу, посилання на документи в IPFS.
Escrow для угод
contract PropertyEscrow {
enum EscrowState { CREATED, FUNDED, CONDITIONS_MET, COMPLETED, DISPUTED, REFUNDED }
struct EscrowDeal {
uint256 propertyTokenId;
address seller;
address buyer;
address notary;
uint256 price;
IERC20 paymentToken;
EscrowState state;
uint256 createdAt;
uint256 completionDeadline;
bytes32[] requiredDocuments;
mapping(bytes32 => bool) submittedDocuments;
}
PropertyRegistry public registry;
mapping(uint256 => EscrowDeal) public deals;
uint256 private _nextDealId;
function createDeal(
uint256 propertyTokenId,
address buyer,
address notary,
uint256 price,
address paymentToken,
uint256 deadline,
bytes32[] calldata requiredDocs
) external returns (uint256 dealId) {
require(registry.ownerOf(propertyTokenId) == msg.sender, "Not owner");
require(!registry.hasActiveLiens(propertyTokenId), "Property encumbered");
dealId = _nextDealId++;
EscrowDeal storage deal = deals[dealId];
deal.propertyTokenId = propertyTokenId;
deal.seller = msg.sender;
deal.buyer = buyer;
deal.notary = notary;
deal.price = price;
deal.paymentToken = IERC20(paymentToken);
deal.state = EscrowState.CREATED;
deal.completionDeadline = block.timestamp + deadline;
deal.requiredDocuments = requiredDocs;
registry.transferFrom(msg.sender, address(this), propertyTokenId);
emit DealCreated(dealId, propertyTokenId, msg.sender, buyer);
}
function fundEscrow(uint256 dealId) external {
EscrowDeal storage deal = deals[dealId];
require(msg.sender == deal.buyer, "Not buyer");
require(deal.state == EscrowState.CREATED, "Wrong state");
deal.paymentToken.transferFrom(msg.sender, address(this), deal.price);
deal.state = EscrowState.FUNDED;
}
function completeDeal(uint256 dealId) external {
EscrowDeal storage deal = deals[dealId];
require(msg.sender == deal.notary, "Not notary");
require(deal.state == EscrowState.FUNDED, "Not funded");
registry.transferFrom(address(this), deal.buyer, deal.propertyTokenId);
deal.paymentToken.transfer(deal.seller, deal.price);
deal.state = EscrowState.COMPLETED;
emit DealCompleted(dealId, deal.propertyTokenId, deal.buyer, deal.seller);
}
function refundExpiredDeal(uint256 dealId) external {
EscrowDeal storage deal = deals[dealId];
require(block.timestamp > deal.completionDeadline, "Not expired");
require(deal.state == EscrowState.FUNDED, "Wrong state");
deal.paymentToken.transfer(deal.buyer, deal.price);
registry.transferFrom(address(this), deal.seller, deal.propertyTokenId);
deal.state = EscrowState.REFUNDED;
}
}
Fractional ownership
contract FractionalProperty is ERC20 {
uint256 public propertyTokenId;
PropertyRegistry public registry;
uint256 public totalShares = 1_000_000;
mapping(address => uint256) public unclaimedRent;
uint256 public accumulatedRentPerShare;
function distributeRent(uint256 amount) external onlyManager {
require(totalSupply() > 0, "No shareholders");
accumulatedRentPerShare += amount * 1e18 / totalSupply();
paymentToken.transferFrom(msg.sender, address(this), amount);
}
function claimRent() external {
uint256 owed = balanceOf(msg.sender) * accumulatedRentPerShare / 1e18 - unclaimedRent[msg.sender];
unclaimedRent[msg.sender] += owed;
paymentToken.transfer(msg.sender, owed);
}
}
Історія транзакцій та ланцюжок володіння
On-chain історія — ключова перевага. The Graph subgraph індексує всі Transfer події та будує повний ланцюжок володіння з цінами угод.
query PropertyHistory($tokenId: String!) {
propertyTransfers(where: { tokenId: $tokenId }, orderBy: timestamp) {
from { id }
to { id }
timestamp
transactionHash
price
notary { id name }
}
liens(where: { propertyId: $tokenId }) {
creditor { id }
amount
expiresAt
active
description
}
}
Що входить у розробку системи
- Документація: архітектура, специфікація смарт-контрактів, керівництво з розгортання.
- Смарт-контракти: Property Registry, Escrow, Fractional Property — з повним покриттям тестами.
- Інтеграція з IPFS для зберігання документів та The Graph для індексації.
- Фронтенд на React + wagmi для перегляду об'єктів та угод; панель нотаріуса для керування обтяженнями та ескроу.
- Налаштування CI/CD, деплой в обрану мережу (Ethereum, Polygon, BNB Chain).
- Навчання вашої команди роботі з системою.
Терміни розробки
| Фаза | Тривалість |
|---|---|
| Phase 1: Property Registry контракт, базові функції реєстрації та обтяжень | 3–4 тижні |
| Phase 2: Escrow контракт, notary flow, атомарні угоди | 2–3 тижні |
| Phase 3: Fractional ownership токени, rent distribution | 2–3 тижні |
| Phase 4: The Graph subgraph, frontend (property browser, ownership history, transaction UI) | 3–4 тижні |
| Phase 5: Аудит смарт-контрактів (особливо ескроу) | 1–2 тижні |
| Повна система | 3–4 місяці |
| MVP без fractional ownership та карти | 6–8 тижнів |
Замовте розробку під ключ — ми оцінимо ваш проєкт за 24 години та запропонуємо оптимальне рішення. Гарантуємо прозорість на кожному етапі. Отримайте консультацію та технічний аудит вашого проєкту.







