ERC-5006: Rental for ERC-1155 Multi-Tokens
ERC-5006 is the ERC-4907 shape ported to ERC-1155: every (tokenId, user) pairing has a separate rental record with its own amount and expiry. Where ERC-4907 grants a single user the user-role of a single ERC-721, ERC-5006 lets a tokenId be split across multiple renters with different expiries. Used by:
- Game guilds lending out fractions of a multi-asset NFT (e.g. 100 weapons of type X across 50 scholars).
- Mass NFT rentals (concert tickets, conference badges issued as ERC-1155 batches).
- Gaming-asset DEXs that rent fractional ownership of high-value multi-tokens.
Required Interface
interface IERC5006 {
struct UserRecord {
uint256 tokenId;
address owner;
uint64 amount;
address user;
uint64 expiry;
}
event CreateUserRecord(uint256 recordId, uint256 tokenId, uint64 amount,
address owner, address user, uint64 expiry);
event DeleteUserRecord(uint256 recordId);
function usableBalanceOf(address user, uint256 tokenId) external view returns (uint256);
function frozenBalanceOf(address owner, uint256 tokenId) external view returns (uint256);
function userRecordOf(uint256 recordId) external view returns (UserRecord memory);
function createUserRecord(address owner, address user, uint256 tokenId, uint64 amount, uint64 expiry)
external returns (uint256 recordId);
function deleteUserRecord(uint256 recordId) external;
}Multiple UserRecords per (owner, tokenId, user) are allowed — each records a separate rental tranche. The owner's balance is frozen while rented (can't transfer the rented portion); the user's usable balance is the sum across non-expired records.
Neo Equivalent: NEP-11 (Divisible) + Per-record Storage
NEP-11 divisible tokens have multi-balance semantics that map to the ERC-1155 shape; ERC-5006 adds rental records on top. The Neo port stores records keyed by an auto-incrementing recordId, plus indices for fast lookup by (user, tokenId) and (owner, tokenId).
public static BigInteger UsableBalanceOf(UInt160 user, ByteString tokenId)
{
var iter = Storage.Find(Storage.CurrentContext, RecordsByUserPrefix(user, tokenId), FindOptions.RemovePrefix);
BigInteger sum = 0;
while (iter.Next())
{
var rec = (Map<string, object>)StdLib.Deserialize((ByteString)iter.Value);
if ((BigInteger)rec["expiry"] >= Runtime.Time)
sum += (BigInteger)rec["amount"];
}
return sum;
}| ERC-5006 (Ethereum) | Neo Equivalent | Notes |
|---|---|---|
createUserRecord(owner, user, tokenId, amount, expiry) | CreateUserRecord(...) returning new recordId | Witness-checked against owner |
deleteUserRecord(recordId) | DeleteUserRecord(recordId) | Owner or user can delete (per spec) |
usableBalanceOf(user, tokenId) | UsableBalanceOf(user, tokenId) summing non-expired records | Iterator over the user index |
frozenBalanceOf(owner, tokenId) | FrozenBalanceOf(owner, tokenId) summing owner-side rentals | |
userRecordOf(recordId) | UserRecordOf(recordId) returning the stored record | Direct read |
Pairs With
- ERC-4907 — single-user ERC-721 rentals. ERC-5006 extends to multi-token / multi-user.
- ERC-6551 — token-bound accounts. A renter could control the tokenId's TBA during the rental window (delegate authorization to the user via the rental record).
- ERC-2981 — NFT royalties. Royalty splits during rentals: configurable split between owner and renter.
- ERC-6982 — default lockable. Locking the owner's rented portion is the natural enforcement mechanism.
Migration Notes
The Neo port is straightforward:
- Inherit
Nep11Tokendivisible base. - Add the records storage (auto-incrementing recordId + records map).
- Add user/owner indices for fast lookup.
- Override the divisible
Transferto honour the frozen-balance constraint.
For game-guild operators porting Solidity ERC-5006 contracts, the record / index pattern is identical; the only Neo-specific idiom is using Runtime.CheckWitness for the owner-on-create and owner-or-user-on-delete authorization.
