NFT Rental Development (ERC-4907)
A gaming guild with 5000 NFT heroes on Polygon faced a problem: how to rent them to newcomers without transferring ownership? Before EIP-4907, rental was implemented through workarounds — token transfer to escrow, trust-based off-chain agreements, or custom role mappings without a unified standard. Any protocol wanting to use someone else’s NFT (game, metaverse, lending) had to write integration per project. Our team — 10+ years in blockchain development, 40+ successful projects — has already implemented dozens of rental solutions based on ERC-4907: from simple contracts to full-fledged marketplaces with off-chain orders.
EIP-4907 solves this cleanly: adds a second address — user — with temporary usage rights, leaving ownership untouched. Time savings on integration — up to 70% compared to custom solutions. We guarantee security and compatibility with all popular networks (Ethereum, Polygon, Arbitrum, Base). Integration with ERC-4907 is 3 times faster than writing a custom rental contract, and the escrow-free approach saves up to 30% gas per operation.
How ERC-4907 Works
The standard extends ERC-721 with two functions and one event:
interface IERC4907 { event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires); 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); } Key point: user is automatically reset to address(0) after expires. No cron-job, no keeper — just a check in userOf():
function userOf(uint256 tokenId) public view virtual returns (address) { if (uint256(_users[tokenId].expires) >= block.timestamp) { return _users[tokenId].user; } return address(0); } owner retains full control: can transfer the token, receive royalties, set a new user. On token transfer, user and expires are automatically reset — protection against the renter retaining rights after ownership change.
Which Architecture to Choose: Escrow-Free or Escrow?
ERC-4907 itself is only a token-level standard. A full rental system requires a rental contract on top.
Approach Comparison
| Characteristic | Escrow-free | Escrow |
|---|---|---|
| Token location | Owner’s wallet | Locked in contract |
| Risk of token loss | Low (no custodial risk) | High if contract flawed |
| Gas per listing | 0 (off-chain signature) | ~50k gas (transfer) |
| Use case | Games, metaverses, lending | Collateral loans, auctions |
Escrow-free (recommended): owner approves the rental contract via approve(), renter pays, contract calls setUser() on behalf of owner. Token stays with owner throughout rental. Escrow-free saves up to 30% gas per rental by avoiding unnecessary transfers.
Gas Cost Comparison
| Operation | Gas (escrow-free) | Gas (escrow) |
|---|---|---|
| Listing | 0 (off-chain) | ~50,000 |
| Rent (1 day) | ~100,000 | ~150,000 |
| Extension | ~40,000 | ~70,000 |
| Return | 0 | ~30,000 |
Gas savings with escrow-free: up to 0.0005 ETH per rental on Ethereum.
Rental Order Structure
struct RentalOrder { address tokenContract; uint256 tokenId; address lender; uint256 pricePerDay; // in wei uint64 minDuration; // in seconds uint64 maxDuration; uint64 deadline; // until when order is valid bytes signature; // EIP-712 lender signature } Off-chain order book (like 0x protocol) + on-chain settlement. Lender signs order off-chain — no gas cost for listing. Renter calls rent(order, duration) — one transaction: payment + setUser().
Automatic Renewal and Early Termination
ERC-4907 does not provide early termination by the lender — expires is immutable after setUser(). For collateral-based rental (protection against asset damage in games), additional logic is needed: renter deposit + lender ability to slash with on-chain proof of violation.
Integration into Games and Protocols
Protocols should replace ownerOf() with userOf():
// Before: require(IERC721(nft).ownerOf(tokenId) == msg.sender, "Not owner"); // After: address user = IERC4907(nft).userOf(tokenId); require(user == msg.sender, "Not authorized user"); For backward compatibility with contracts that don’t support ERC-4907: a wrapper contract that wraps a standard ERC-721 into ERC-4907. Owner deposits the original token, gets a wrapped version with rental functionality.
Common Mistakes
- Forgetting to check
expiresinuserOf()— use the built-in standard check. - Not resetting
useron transfer — the standard does it automatically. - Using
ownerOf()instead ofuserOf()in usage logic — losing renters. - Not signing orders with EIP-712 — listing will require gas.
- Not protecting
setUser()from direct malicious calls — use onlyOwner modifier.
What Is Included in Development?
- ERC-4907 contract (if collection is new) or wrapper for an existing one
- Rental marketplace contract: off-chain orders with EIP-712 signatures, on-chain settlement
- Pricing logic: fixed price/day, Dutch auction for decreasing price over time
- Frontend: listing, search for available tokens, one-click rental
- Integration with consumer protocol: replacing
ownerOfwithuserOf
How We Develop NFT Rental
- Analysis: define rental logic requirements, durations, pricing.
- Design: smart contract architecture, choose between escrow-free and escrow.
- Implementation: Solidity code using Foundry, testing (unit + fuzzing with Echidna).
- Audit: reentrancy checks, gas optimization, formal verification of key functions.
- Deployment: configure contracts for chosen network (Ethereum, Polygon, Arbitrum), verify code on Etherscan.
- Integration: connect frontend, write developer documentation.
Timeline Estimates
- Just ERC-4907 contract + basic rental: from 2 days.
- With off-chain order book, frontend, and game contract integration: 4-5 days.
Cost is calculated individually based on complexity and scope. Gas savings up to 30% reduce operational costs — at typical load, about $0.05 per transaction. Contact us for a consultation on your project. Order NFT rental development today.







