Розробка платформи оренди NFT
ERC-721 та ERC-1155 спочатку не передбачали оренду — токен либо належить адресі, либо ні. Спроби реалізувати оренду через custodial-депозит (користувач передає NFT на контракт, отримує wrapped-версію) створюють поверхню атаки та погану UX. Стандарт ERC-4907 закрив цей пробіл, введши роль user у доповненнні до owner, з expiry timestamp. Але навіть з ERC-4907 потрібно вирішувати нетривіальні завдання: управління заставою, розподіл доходу, flash renting, cross-chain оренду.
Моделі оренди: залог проти залогу-free
Два принципово різних підходи, вибір залежить від use case:
Collateral-based — орендатор блокує залог, що перевищує floor price NFT. Використовується для ігрових активів з високою ліквідністю. Ризик: floor price волатильна, механізм ліквідації повинен працювати без оракулів з мінімальною latency. Для цього інтегруйте Chainlink Price Feeds або TWAPs з Uniswap v3 pools із достатньою глибиною.
Collateral-free (scholarship model) — власник делегує використання без передавання ownership. Класичний case — Axie Infinity scholarships. Реалізується через ERC-4907 setUser() + whitelist орендаторів на рівні ігрового сервера. Простіший контракт, але off-chain інфраструктура складніша.
// Мінімальна реалізація ERC-4907 з revenue sharing
interface IERC4907 {
function setUser(uint256 tokenId, address user, uint64 expires) external;
function userOf(uint256 tokenId) external view returns (address);
function userExpires(uint256 tokenId) external view returns (uint256);
}
contract RentalMarket {
struct RentalTerms {
uint256 pricePerDay;
uint256 maxDuration;
uint256 collateralRequired;
address paymentToken; // address(0) = native
uint16 protocolFeeBps; // basis points
}
}
Смарт-контракти: що реально складно
Expiry enforcement — ERC-4907 не викликає callback при завершенні оренди. userOf() повертає address(0) якщо block.timestamp > userExpires, але сам токен не «звільняється». Ігрові сервери мають polling-ити стан або підписуватися на events. Альтернатива — Gelato Automation для on-chain уведомлень при истечении аренди.
Вложена оренда (subletting) — власник хочет дозволити орендатору здавати токен далі. Стандарт не заборняє, але потрібно дерево арендних відносин і коректний розподіл доходу. Реалізуємо через mapping rentals[tokenId][] з деревом залежностей та reentrancy guard на кожному рівні.
Flash renting — оренда та використання в одній транзакції, аналог flash loans. Корисно для one-time actions (mint через NFT-gate, vote snapshot). Контракт приймає callback інтерфейс, передає user права, чекає виконання, откатывает якщо flashRent не завершена коректно.
Розподіл доходу — якщо NFT генерує in-game rewards, потрібен сплиттер: owner отримує X%, renter Y%, protocol fee Z%. Використовуємо pull-payment pattern (Escrow) замість push щоб уникнути gas griefing.
Індексація та пошук
Граф даних для rental платформи складніше, ніж для простого marketplace. Необхідно відслідковувати:
- Активні аренди з expiry timestamps
- Історію аренд на токен (для репутації орендаторів)
- Прибутковість по кожному NFT (APR для власників)
The Graph з кастомним subgraph — стандартний вибір. Схема entities:
| Entity | Ключові поля |
|---|---|
| Rental | tokenId, owner, user, startTime, endTime, pricePerDay, collateral |
| RentalOffer | tokenId, lister, pricePerDay, minDuration, maxDuration, active |
| RenterProfile | address, totalRentals, disputeCount, reputationScore |
Для real-time обновлення (потрібні при завершенні оренди) — WebSocket підписка на контрактні события через Alchemy або Infura, bridge до The Graph через Apollo subscriptions.
Безпека: специфіка rental контрактів
Кілька атак, специфічних саме для rental:
Approval drain — якщо орендодателем виділено approval на контракт, а контракт не перевіряє, що transferFrom вызывается тільки при активній оренді, атакуючий може вивести NFT. Рішення: контракт повинен бути custodian (тримати NFT у себе) або використовувати ERC-4907 без custody.
Timestamp manipulation — validators можуть маніпулювати block.timestamp в межах ~15 секунд. Не критично для оренди на дні, але для flash renting з секундною гранулярністю потрібен block.number як додатковий параметр.
Reentrancy через ERC-721 receiver — при поверненні NFT контракт вызывает onERC721Received. Якщо owner — смарт-контракт з логікою в цьому callback, можлива reentrancy. Везде ставимо nonReentrant та дотримуємось Checks-Effects-Interactions.
Oracle manipulation — для collateral-based оренди з Chainlink важливо використовувати latestRoundData() з перевіркою updatedAt та stale threshold. Застарілий price feed = некоректна liquidation.
Frontend та UX
Rental платформа вимагає нестандартного UI — власник бачить «прибутковість портфеля», орендатор бачить «доступні до оренди активи». Розробляємо на React + wagmi v2 + viem. Ключові компоненти:
- Portfolio dashboard — список owned NFTs з метриками: поточний статус, earned revenue, suggested rental price (on-chain дані + floor price від Reservoir API)
- Rental marketplace — фільтрація по collection, price range, duration, required collateral
- Rental management — активні аренди, time remaining (countdown), early termination flow
Wallet integration через RainbowKit з ERC-4907-aware display (показуємо userOf() vs ownerOf() в NFT viewer).
Stack та інфраструктура
- Контракти: Solidity 0.8.x, Hardhat + Foundry для тестування, OpenZeppelin базові компоненти
- Тестування: Foundry fuzzing на rental edge cases (expiry == current block, collateral == 0, nested rentals)
- Indexing: The Graph hosted або self-hosted Graph Node
- Backend: Node.js / TypeScript API для off-chain логіки (репутація, уведомлення)
- Notifications: push уведомлення через EPNS (Ethereum Push Notification Service) при завершенні оренди
- Networks: Ethereum mainnet + L2 (Polygon, Arbitrum) — rental платформи чутливі до gas costs







