# Introduction

### **What is reNFT?**[​](https://docs.renft.io/docs/intro#what-is-renft) <a href="#what-is-renft" id="what-is-renft"></a>

reNFT is a multi-chain NFT rental protocol and platform that can be whitelabel integrated into any project to enable collateral-free in-house renting, lending, and reward share (scholarship automation).

### Who should use reNFT?[​](https://docs.renft.io/docs/intro#who-should-use-renft) <a href="#who-should-use-renft" id="who-should-use-renft"></a>

reNFT is built for developers who are working on web3 projects. It's our goal to make your life easier by rapidly enabling rental functionality.

### **NFT rentals**[​](https://docs.renft.io/docs/intro#nft-rentals) <a href="#nft-rentals" id="nft-rentals"></a>

NFT rentals have many use cases, just like rental has in the real world. Currently, NFT rentals are gaining traction in the gaming industry, but they are also becoming popular in token-gated events and communities. Click [**here**](/general-info/rental-use-cases) to learn more about different rental use cases.


# Rental Use Cases

This is just a small list of all the endless possibilities of NFT rentals. We are very excited about the creative ideas of the web3 community to leverage the reNFT rental protocol!

### Gaming assets[​](https://docs.renft.io/docs/Getting-started/rental-use-cases#gaming-assets) <a href="#gaming-assets" id="gaming-assets"></a>

A popular NFT game is Axie Infinity where players can let their in-game assets, called Axies, fight against each other and earn Smooth Love Potion tokens through that. (Play-to-earn) Playing the game requires you to have at least 3 Axies, so there is a high-cost barrier for new people to even try out the game. To overcome this hurdle the Axie community has created the so-called Axie scholarship program where players can lend their Axies to other players so they can play the game without having to buy Axies. This trend is emerging among all games in the space.

### Event tickets[​](https://docs.renft.io/docs/Getting-started/rental-use-cases#event-tickets) <a href="#event-tickets" id="event-tickets"></a>

What if you have an NFT ticket for an event, but you can’t attend the event? You could sell the ticket, but the ticket might have future utility. So if you want to keep the NFT, you can lend it!

When your ticket is rented, the renter can attend the event while you keep your NFT and earn rent.

### Virtual land[​](https://docs.renft.io/docs/Getting-started/rental-use-cases#virtual-land) <a href="#virtual-land" id="virtual-land"></a>

What if you want to host an event in the metaverse, but you don’t have (enough) land? You can rent land from a landowner and use his land to host your event! This is way cheaper and easier than buying land yourself.

Users will be able to rent virtual ad spaces and in-game billboards making NFT rentals an important economic factor in the new age of digital marketing. We believe over time users will spend more and more time in virtual worlds, experiences, and games. Therefore in-game advertising could become an important part of the marketing strategy of companies. Wouldn’t it be amazing to rent an in-game billboard at a great location, just like you would at Times Square in New York?

### Temporary assets[​](https://docs.renft.io/docs/Getting-started/rental-use-cases#temporary-assets) <a href="#temporary-assets" id="temporary-assets"></a>

What if you have a high-end virtual casino and you require people to wear a full black suit from a major brand. By enabling rentals, you can still make this casino accessible for people with a smaller budget and therefore you can serve a broader audience.

### Subscriptions[​](https://docs.renft.io/docs/Getting-started/rental-use-cases#subscriptions) <a href="#subscriptions" id="subscriptions"></a>

A great idea for subscriptions is rental pools. You can, for example, let a user pay 100 USDC per month and deliver an automatic weekly digital wardrobe update. This would be amazing for people who want to wear new things every week, but don't want the hassle of figuring out what to wear.


# Compatible Blockchains

reNFT is a fully blockchain agnostic protocol. We strive to be compatible with any blockchain that has compelling use-cases and activity for rental infrastructure. At first, blockchains with the most games and activity are prioritized. If you'd like reNFT to add or prioritize a chain, reach out [here](/about-renft/contact)!

**Existing Blockchains:**

* Ethereum Mainnet
* Polygon
* Avalanche Mainnet C-Chain
  * Subnets are implemented when requested on a per case basis


# Whitelabel Interface

### **Whitelabel**[​](https://docs.renft.io/docs/Getting-started/user-experience#whitelabel) <a href="#whitelabel" id="whitelabel"></a>

reNFT can be used as a fully whitelabel solution, this means that you can seamlessly integrate the reNFT protocol in your project while keeping/maintaining your project's front-end or gaming interfaces.

### **Dedicated page**[​](https://docs.renft.io/docs/Getting-started/user-experience#dedicated-page) <a href="#dedicated-page" id="dedicated-page"></a>

If you prefer to save time and headaches, we also offer dedicated integration pages on the reNFT front-facing platform. You can find the platform [here](https://market.renft.io)!

An example of a dedicated page on the reNFT platform can be found [here](https://market.renft.io/collections/castle-crush?chain=43114)\
An example of a collection page that we can tailor to your needs can be found [here](https://market.renft.io/collections/castle-crush?chain=43114)

If you’d like to use a dedicated page, please click [here](/about-renft/contact) to reach out to us to learn more.


# Custom Solutions

You might have a specific feature that you’d like to see built into reNFT. We completely understand that and we’re more than happy to tailor the protocol to your project or ecosystem's needs. As of now, the reNFT team decides what features are prioritized.

This prioritization is based on the transaction volume of the project that requests the feature and the number of times this feature has been requested. In the future, the DAO will decide what features will be prioritized.

We'd love to chat, feel free to [contact us](/about-renft/contact) about tailoring a solution to your project's needs!


# Protocol Composability

We believe an immense number of NFTs will be locked in smart contracts in the coming future. Therefore, we collaborate with other (financial) protocols to unlock some exciting use.

These protocols lock NFTs in smart contracts to enable loans, fractionalization, staking, or other utility.

By collaborating, we allow locked assets to be rented out through our use-right model. Therefore users can earn yield while their NFT is locked/being utilized in other protocols.

Imagine a scenario in the real world where you took a loan from the bank to purchase a home or property, but then could not rent that property out to a tenant.. we fix this problem for NFTs!

Examples:

* Take a loan against your NFT while renting it out
* Fractionalize your NFT while renting it out
* Buy now, pay later. Rent out your NFT while paying off your debt
* And more!


# Protocol Fee

### Protocol fee[​](https://docs.renft.io/docs/Getting-started/pricing#protocol-fee) <a href="#protocol-fee" id="protocol-fee"></a>

The reNFT protocol is currently free because we want to stimulate adoption as much as possible.

The future fee will be a percentage fee per transaction. The revenue will be shared with the integrated project. The total fee will be determined by the integrated project and the reNFT DAO.

reNFT is operating as a DAO, therefore we can propose different revenue split options between the integrated project and reNFT. If, for example, your project has a lot of rental volume, we can propose to change the split in favor of your project.

We prefer to stake the revenue that we receive from your project back into your ecosystem.

### Implementation costs[​](https://docs.renft.io/docs/Getting-started/pricing#implementation-costs) <a href="#implementation-costs" id="implementation-costs"></a>

The implementation should be so easy that you don’t need help from us, but we’re more than happy to help! There will be no implementation costs involved.

If you’re looking for a tailored solution, please click [here](/general-info/custom-solutions).


# Frequently Asked (FAQ)

### Can users pay in the native token of a project?[​](https://docs.renft.io/docs/Getting-started/FAQ#can-users-pay-in-the-native-token-of-a-project) <a href="#can-users-pay-in-the-native-token-of-a-project" id="can-users-pay-in-the-native-token-of-a-project"></a>

Yes. When reNFT is integrated into your project, users can pay with your native token.

### Why shouldn’t we build a rental solution ourselves?[​](https://docs.renft.io/docs/Getting-started/FAQ#why-shouldnt-we-build-a-rental-solution-ourselves) <a href="#why-shouldnt-we-build-a-rental-solution-ourselves" id="why-shouldnt-we-build-a-rental-solution-ourselves"></a>

Great question! First of all, building a rental solution is way more complex and time-consuming than you might think. Since it’s hard enough already to find a talented team to build a successful project, we believe you should spend their time on your core business, not rental infrastructure.

Another big reason is our partnerships. We will partner with projects that enable fractionalization or provide loans with NFTs as collateral. This means that you can lend your NFT and receive a collateralized loan at the same time.

We also have partnerships with the biggest gaming guilds. We closely work together with them to tailor our protocol to their needs, therefore guilds will prefer games to work with reNFT in the future.

### **What if I want to send an airdrop to the renter?**[​](https://docs.renft.io/docs/Getting-started/FAQ#what-if-i-want-to-send-an-airdrop-to-the-renter) <a href="#what-if-i-want-to-send-an-airdrop-to-the-renter" id="what-if-i-want-to-send-an-airdrop-to-the-renter"></a>

In this case, the project has to look at the API to see who the renter is and airdrop it to that wallet address, instead of the actual NFT holder.

### If the smart contract gets hacked, who is responsible?[​](https://docs.renft.io/docs/Getting-started/FAQ#if-the-smart-contract-gets-hacked-who-is-responsible) <a href="#if-the-smart-contract-gets-hacked-who-is-responsible" id="if-the-smart-contract-gets-hacked-who-is-responsible"></a>

We extensively test our contracts and let them be audited by renowned parties before launching them. Although we do everything to make our smart contracts as safe as possible, we can’t guarantee that they can’t be hacked. If one of the reNFT smart contracts would get hacked, the owner of the NFT is responsible for a potential loss.

The reNFT team at no point has access to any asset.

Our V1 contracts are not formally audited, but they were reviewed by several developers. You can find the contract here: <https://etherscan.io/address/0xa8d3f65b6e2922fed1430b77ac2b557e1fa8da4a>

Our V2 contracts, which will be released soon, will be formally audited.

### Can my NFT be automatically put up for rent again after the rental period has ended?[​](https://docs.renft.io/docs/Getting-started/FAQ#can-my-nft-be-automatically-put-up-for-rent-again-after-the-rental-period-has-ended) <a href="#can-my-nft-be-automatically-put-up-for-rent-again-after-the-rental-period-has-ended" id="can-my-nft-be-automatically-put-up-for-rent-again-after-the-rental-period-has-ended"></a>

Yes, in the collateral-free solution, this is by default the case. Your NFT stays available for rent until you withdraw the NFT from the smart contract. In the collateralized solution, the NFT has to be returned by the renter first.

### What happens if an NFT is returned before the rental period has ended?[​](https://docs.renft.io/docs/Getting-started/FAQ#what-happens-if-an-nft-is-returned-before-the-rental-period-has-ended) <a href="#what-happens-if-an-nft-is-returned-before-the-rental-period-has-ended" id="what-happens-if-an-nft-is-returned-before-the-rental-period-has-ended"></a>

When an NFT is returned before the rental period has ended, the smart contract refunds the renter for the unused time.

For example, you rent an NFT for 1 day and you return the NFT after 12 hours. The smart contract will refund you for the remaining 12 hours.

### What token standards do you support?[​](https://docs.renft.io/docs/Getting-started/FAQ#what-token-standards-do-you-support) <a href="#what-token-standards-do-you-support" id="what-token-standards-do-you-support"></a>

We currently support ERC-721, ERC-1155 and blended assets. The Sandbox is an example of a collection that has blended assets.


# Collateral-Free

Lender's NFT gets staked into our smart contract and is not transferred to renter. Integrating projects use our API to obtain the list of renters.

We have two flavours of our collateral free solution at the moment. One without the reward share component, and one with. Read on to learn how they operate on a high level.

## No Reward Share

Our collateral-free solution enables NFT rentals without collateral. We enable this by escrowing the NFT in our smart contract. The project that wants to make use of collateral-free solution must check our API to see if someone is renting an NFT, therefore this solution requires some integration, albeit minimal. If you're looking to integrate collateral-free rentals, check our [integration guide](/developers/integration-guide).

![](/files/6UCHrzul7adDRgBetgam)

This solution is similar to renting a house. The owner of the NFT decides the daily rental price, the currency he/she wants to get paid in, and the maximum rental duration. After the lender puts it up for rent, the renter can decide how long he/she wants to rent the NFT. The renter is required to pay the total rental price (daily rental price \* rental duration). When the tokens have been received in the smart contract, the renter has access to the utility of the NFT.

#### **Example:**[​](https://docs.renft.io/docs/Getting-started/rental-solutions#example) <a href="#example" id="example"></a>

Jack owns a Galaxy Fight Club NFT and wants to put it up for rent.

Jack wants to receive 20 USDC per day and is prepared to rent out his NFT for 14 days maximum.

Sam decides to rent the NFT for 7 days. Therefore he has to pay 140 USDC (7 \* 20) + gas fees.

After 7 days, Sam’s use right expires and therefore he doesn’t have access to the NFT anymore.

Note, it is possible to terminate the rental before the full duration. So, Sam could have returned the NFT earlier and would get back the money from his up front payment that is proportional to unused time.

## With Reward Share

Our collateral-free reward share solution enables peers and guilds to automate the scholarship model that first appeared in Axie Infinity.

In this scholarship model, NFT owners rent out their NFT and share the earnings with gamers, also known as the 'Scholars'.

Axie Infinity doesn't provide a native in-game function to do this and therefore giving access to the NFTs, keeping track of earnings and payouts are all manual processes. As you can imagine, this is very time-consuming.

reNFT works closely together with major guilds to solve these inefficiencies by automating the whole process. We proudly present our reward share solution.

When a game integrates reNFT's reward share solution, guilds and peers are able to rent out their NFT and share the earnings with the gamer automatically.

Click [here ](/video-tutorials/castle-crush-reward-share/how-to-lend)for a tutorial on how to lend your NFT.

![](/files/QeV4eOhTQ7P9HMo0N8mE)

#### **Example:**[​](https://docs.renft.io/docs/Getting-started/rental-solutions#example-1) <a href="#example-1" id="example-1"></a>

Jack owns a Castle Crush NFT and wants to earn rewards from the game, but doesn’t have time to play. By playing the game, you can earn $ACS. Jack decides to lend the NFT via the reward share solution. While putting the NFT up for rent, Jack determines the reward share split percentage. In this example, we use 50/50.

Sam rents the NFT and starts playing the game. After playing for a week, he earned 100 $ACS. Because of the reward share split, Sam receives 50 $ACS and Jack does too.

### Splitting earnings with a third party

You might want to share game rewards with third parties such as managers. While renting out your NFT, you can add numerous wallet addresses to split the game rewards with.

**Example:**

* Lender: 45% of earnings
* Gamer: 45% of earnings
* Manager: 10% of earnings

### Whitelisting

If you want a specific person to be able to rent your NFT, you can use the whitelist feature. While putting your NFT up for rent, add the wallet addresses you want to be eligible to rent the NFT.

This is a very useful feature if you want to work with specific gamers you collaborate with.


# Collateralized

We advise against using this solution, because collateral is a huge barrier to entry. However, should you wish to lend / rent, there is no integration required.

### **Collateralized rental**[​](https://docs.renft.io/docs/Getting-started/rental-solutions#collateralized-rental) <a href="#collateralized-rental" id="collateralized-rental"></a>

Our collateralized solution transfers the NFT to the wallet of the renter. This means that the renter can do anything he wants with the rented NFT. Therefore, collateral is required to compensate the lender if the NFT is not returned. This is a huge barrier for rentals because most of the time people rent an NFT due to a lack of funds to buy it themselves.

Since the NFT is in the wallet of the renter, an integration with reNFT is not necessary and therefore you can use the NFT as if you were the owner of it. This is the biggest advantage of collateralized rentals, but there are also a lot of disadvantages. A few of them are:

* A collateral is a huge barrier for people to rent because rent often makes sense due to a lack of funds
* If the value of the NFT changes and becomes higher than the collateral, the lender is at risk
* The renter can use the NFT as collateral for a loan without asking permission from the lender

![](/files/00ADi9wsTy7EU6I5Qyrw)


# Integration Guide

Step-by-step instructions on how to integrate our collateral-free solution into your project

First of all, to obtain the API key, please fill out the following [form](https://renft.notion.site/Project-Submission-Form-e61df64eeea54f96a561b522b1e4af03).

Next, depending on which solution you would like: no reward share or with reward share, follow the below instructions.

## Traditional Rentals (aka Collateral Free; no reward share)

There isn't much to be done here other than recognizing the renters that you get back via making an API call.

We are currently working on our very own API. However, in the interim, you are free to make GraphQL requests to an external API provider (without requiring any API keys). You can read about how to get the list of active renters [here](/developers/querying-renfts-on-chain-data).

## Reward Share

The "No Reward Share" section applies in its entirety here as well. However, there is an extra step in terms of handling the payment of the rewards. Originally, the integrating project could call a particular function on the smart contract whilst sending the reward token and our contract would handle the distribution for you. Our newer version works differently, to minimize the transaction cost for you. Rather than going for the push payment approach, we have designed the contract to utilize the pull approach.

Now, each individual player is responsible for collecting the rewards they have accumulated. This means, that the integrating project simply sends a lump sum of the reward token into our smart contract once in a while that then gets re-distributed as already stated.

## DApp customization options

You are able to specify the banner on our market page for your collection. For example, this is how it would look like:

<figure><img src="/files/e5bGYS5W203KDkdhoIeQ" alt=""><figcaption></figcaption></figure>

You can provide us with a 100 quality jpq, 2880x1000. For example for the above, it would look something like:

<figure><img src="/files/blJfVEWFxChXSVKcFTkb" alt=""><figcaption></figcaption></figure>

You can also specify your game token to be used for lendings and rentals (note we do not support cross-chain payments yet, so ensure that your payment token and collection live on the same chain). If this is not provided, then the default options like: WETH, USDC, DAI, USDT will be used.

To recap, you can personalise the following options:

* marketplace banner image
* payment token in which your lendings and rentals will be dealt in


# SDK

Only use this if you are interested in your very own marketplace.

In other words, if you plan to support rentals on your own dapp, then this is for you. This SDK lets you interact with our smart contracts, it's a `typescript` library.

The latest version can be found [here](https://github.com/re-nft/sdk). If you have any questions, feel free to [contact us](/about-renft/contact)!


# @renft/sdk@^v6.0.0


# Interacting with Smart Contracts

How to find the right smart contract to use for your dApp?

[reNFT is rental infrastructure for the metaverse](https://www.renft.io/), which means we've designed our SDK to be abstract enough to support redeployments on any kind of arbitrary blockchain network; this ensures we provide battle-tested, exhaustive and truly decentralized rental infrastructure for the unbounded range of tokenized assets that support the ongoing Web3 revolution.

NFTs and their use cases are fundamentally rewriting about how we think about games, music, art, marketplaces and events; and preconceived notions of rentals are no exception. The reNFT SDK fully embraces the abstract and diverse inevitability of Web3, and in the following documentation, we're going to talk through how you can leverage this to your full advantage.

### Selecting a Deployment

In order to interact with a reNFT smart contract, we quickly need to run through a concept called `Deployment`s. These are the mechanism by which we enable deterministic resolution of the interfaces to different rental contracts that have been deployed across the metaverse.

For example, a `Deployment` respects the ideas that:

* Different smart contracts have different purposes; such as orchestrating trustless collateralized lending, non-collateralized lending, reward sharing between counterparties and more!
* In future, we expect updated versions of these smart contracts can be deployed at whim, flaunting new-and-improved interfaces and functionality, and we wish to take advantage of these easily without *invalidating* or obscuring these differences in pre-existing client implementations.
* Our infrastructure needs to respect that blockchains enable the same smart contracts to be deployed to multiple different addresses.
* Our smart contracts can even be deployed across many kinds of blockchains!

For these reasons, we need to propose a mental model which encapsulates the unique challenges of building client applications which scale to support the endless possibilities of what can be expressed on-chain.

> ⚠️ It's important to select the correct deployment for your intended use case.

In the reNFT SDK, a `Deployment` takes the following form:

```typescript
{
  readonly contractType: ContractType;
  readonly version: Version;
  readonly contractAddress: string;
  readonly network: Network;
}
```

This is all the information we will need to encapsulate any smart contract deployment out there in the metaverse. Really.

Let's see how we'd find a deployment of our collateral-free contract, nicknamed *Sylvester*, on the [Polygon](https://polygon.technology/) network:

```typescript
import {
  findDeployments,
  NETWORK_POLYGON_MAINNET,
  ContractType,
} from "@renft/sdk";

const [...maybeMatchingDeployments] = findDeployments({
  network: NETWORK_POLYGON_MAINNET,
  contractType: ContractType.SYLVESTER,
});
```

This would return all available instances of Sylvester on Polygon. At the time of writing, this would actually return two different deployments you can use: `v0` and `v1`!

You can add further properties to refine a particular deployment configuration to ensure only a single resolution is found, for example:

```typescript
import {
  findDeployments,
  NETWORK_POLYGON_MAINNET,
  ContractType,
} from "@renft/sdk";

const [deployment] = findDeployments({
  network: NETWORK_POLYGON_MAINNET,
  contractType: ContractType.SYLVESTER,
  contractAddress: '0x4e52b73aa28b7ff84d88ea3a90c0668f46043450',
});
```

In this instance, we have specified sufficient criteria to resolve a single deployment of Sylvester on Polygon.

In most instances, you'll find it a lot easiest to reference an existing deployment directly, for example:

```typescript
import { DEPLOYMENT_SYLVESTER_POLYGON_MAINNET_V1 } from "@renft/sdk";
```

The advantage of using a specific deployment reference is that we receive a narrowed-type of the deployment, instead of dealing with deployment attributes which are scoped to the search criteria when specified in a call to `findDeployments`. This leaves no room for ambiguity in the functional properties the interface supports, and allows TypeScript to helpfully narrow this for you.

Different versions of a deployment specify different call interfaces; for example, the `lend` function of Sylvester `v0` was extended in Sylvester `v1` to provide additional functionality such as the ability to control whether lendings are permitted to auto-renew upon completion of a cycle. This helps lenders earn more by automatically re-enabling the availability of their rental, and simultaneously costs them less [gas](https://ethereum.org/en/developers/docs/gas/) in the process.

### Resolving a Smart Contract

Once we've selected a `Deployment`, it's super easy to resolve the equivalent `ethers`-compatible `Contract` object.

To do this, we make a call to `getRenftContract()`:

```typescript
import {
  DEPLOYMENT_AZRAEL_ETHEREUM_MAINNET_V0,
  getRenftContract,
} from "@renft/sdk";
import { ethers } from "ethers";

const collateralizedLendingContract = getRenftContract({
  deployment: DEPLOYMENT_AZRAEL_ETHEREUM_MAINNET_V0,
  signer: ethers.Wallet.createRandom(),
});

```

Notice in this instance that to resolve a smart contract using a `deployment`, we must also provide a `signer`. This signer is responsible for *signing* (authenticating) transactions made using the contract, so you'll usually want to create a new `Contract` instance whenever a new `Wallet` is connected.

The `getRenftContract()` function is cheap to invoke, so to avoid unnecessary complexity or potential errors caused by accidentally holding onto stale `Contract` references, it usually makes sense to call `getRenftContract()` immediately before making a transaction opposed to caching them.

The `Deployment` you provide to `getRenftContract()` is all the context you'll need to start creating your very first transactions.

> ⚠️ Remember that `getRenftContract()` may not return a `Contract` if the `deployment` you have passed is invalid; this can happen if your search query passed into `findDeployments` fails to resolve to a valid `Deployment`.&#x20;

It is always good practice to check that `getRenftContract()` has returned a valid `Contract` by using a conditional check for truthiness of the result object, i.e.

<pre class="language-typescript"><code class="lang-typescript"><strong>import {
</strong>  findDeployments,
  NETWORK_AVALANCHE_MAINNET,
  ContractType,
} from "@renft/sdk";

const [maybeDeployment] = findDeployments({
  network: NETWORK_AVALANCHE_MAINNET,
  contractType: ContractType.SYLVESTER,
});

const maybeContract = getRenftContract({
  deployment: maybeDeployment,
  signer: ethers.Wallet.createRandom(),
});

if (!maybeContract) throw new Error("1) What");

</code></pre>


# Collateral-Free Integration Guide

The official instructions on how to interact with our open Collateral-Free rental contracts.

> This tutorial was written for SDK version `6.0.0`.

![reNFT collateral-free contract flows](/files/18HUCzSwTvkM1RT33qJf)

### Lending and Renting NFTs[​](https://docs.renft.io/docs/Developers/collateral-free#lendrent-nfts-in-app) <a href="#lendrent-nfts-in-app" id="lendrent-nfts-in-app"></a>

To interact with our smart contracts, we always recommend using our [SDK](https://github.com/re-nft/sdk). We view the SDK as the source of truth for all of our deployments and business logic; most importantly, it versions where our smart contracts reside in the metaverse and defines objectively how they work.

To work with collateral-free lendings, we'd use the `Sylvester` contract:

```typescript
import {
  getRenftContract,
  DEPLOYMENT_SYLVESTER_ETHEREUM_MAINNET_V0,
  SylvesterV0FunctionInterface,
} from "@renft/sdk";

import { ethers } from "ethers";

const signer = ethers.Wallet.createRandom(); // In practical dApps, this would be the user's wallet!

const renft: SylvesterV0FunctionInterface = getRenftContract({
  deployment: DEPLOYMENT_SYLVESTER_ETHEREUM_MAINNET_V0,
  signer,
});
```

> 💭 We name our contracts after famous cats! You can find the name mappings [here](/developers/renft-contracts-addresses). Meow!

### Batching[​](https://docs.renft.io/docs/Developers/collateral-free#batching) Transactions <a href="#batching" id="batching"></a>

Any of the following functions support batching. This is shown below for the `lend()` instruction, where the user lends an [AstroCat](https://opensea.io/collection/renftlabs) and a [CatPlsr](https://opensea.io/assets?search\[query]=CatPlsr) within the *same function call*:

```typescript
import { NFTStandard, PaymentToken, packPrice } from "@renft/sdk";

const astroCatLendingArgs = [
  NFTStandard.E1155,
  "0x0db8c099b426677f575d512874d45a767e9acc3c",
  "1",
  1,
  1,
  packPrice("1"),
  PaymentToken.WETH,
];

const catPlsrLendingArgs = [
  NFTStandard.E1155,
  "0x0db8c099b426677f575d512874d45a767e9acc3c",
  "2",
  1,
  1,
  packPrice("0.5"),
  PaymentToken.WETH,
];

const lendingArgs = astroCatLendingArgs.map((value, index) => 
  [value, catPlsrLendingArgs[index]]
);

await renft.lend(...lendingArgs);
```

### Lending <a href="#lend" id="lend"></a>

dApps invoke `lend()` when they wish to create a new on-chain lending. A lending is when a market maker asserts that they wish to allow other users to temporarily have rights to the asset for the duration of the rental.

Since the `lend()` function is designed to batch multiple NFTs together, you can create a single-element lending by using single-element arrays for each of the required parameters:

```typescript
import { NFTStandard, PaymentToken, packPrice } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendAmount = 1; // Quantity of the NFT to lend.
const maxRentDuration = 1; // Duration is measured in days.
const dailyRentPrice = packPrice("1"); // Create a properly formatted rental price.
const paymentToken = PaymentToken.WETH;

await renft.lend(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendAmount],
  [maxRentDuration],
  [dailyRentPrice],
  [paymentToken]
);
```

### Rent[​](https://docs.renft.io/docs/Developers/collateral-free#rent)ing <a href="#rent" id="rent"></a>

A renting is created when a user discovers a compelling lending on the blockchain and decides to take the maker up on their offer. In this instance, the user is the *taker* of the lending. Much like the previous example, we call the `rent()` function with vectorized data representing each individual token to be rented in a gas-optimized batch.

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1"; // this information is pulled from the subgraph
const rentDuration = 1; // in days
const rentAmount = 1;

await renft.rent(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
  [rentDuration],
  [rentAmount]
);
```

### Stopping a Rental <a href="#stop-rent" id="stop-rent"></a>

For a non-collateralized rental, even though no *real* possession of the NFT is given (it is a virtualized rights-to-ownership), the renter must signal that they have concluded "using" the NFT with a call to `stopRent()`.

If the renter fails to make this call, the lender is permitted to invoke `claimRent()`, explained in the following section, to redeem the full amount of rent.

> 💭 Invocations to `stopLend()` are disabled until the lender calls `claimRent()` first.[​](https://docs.renft.io/docs/Developers/collateral-free#stop-rent)

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1"; // from subgraph
const rentingID = "1"; // from subgraph

await renft.stopRent(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
  [rentingID],
);
```

### Claiming Rent[​](https://docs.renft.io/docs/Developers/collateral-free#claim-rent) <a href="#claim-rent" id="claim-rent"></a>

Lenders can claim rent by calling the `claimRent()` function.

Remember, the smart contract enforces the rules of lending and renting; you can try to claim the rent of an ongoing lending which doesn't belong to you, but the transaction will be reverted!

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1";
const rentingID = "1";

await renft.claimRent(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
  [rentingID],
);
```

### Stopping a Lending[​](https://docs.renft.io/docs/Developers/collateral-free#stop-lend) <a href="#stop-lend" id="stop-lend"></a>

Finally, there's the `stopLend` function, which is called by the lender. This prevents the provided assets from being rented out any longer, much to the chagrin of prospective renters.

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1";

await renft.stopLend(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
);
```

> To learn about more about how we determine the status of a particular lending or renting, check out [this guide](/developers/querying-renfts-on-chain-data)!

### How to unpack data?[​](https://docs.renft.io/docs/Developers/collateral-free#unpacking-data) <a href="#unpacking-data" id="unpacking-data"></a>

In reNFT, prices are returned in a custom format. This is a performance optimization which enables an entire lending to fit snugly inside a single storage slot, which saves gas.

To unpack them, we can use the `unpackPrice()` function:

```typescript
import { PaymentToken, unpackPrice } from "@renft/sdk";

// Convert a low-level representation of an ERC-20 used on
// the marketplace into a TypeScript-friendly enum.
const parsePaymentToken = (tkn: string): PaymentToken => {
  switch (tkn) {
    case "0":
      return PaymentToken.SENTINEL;
    case "1":
      return PaymentToken.WETH;
    case "2":
      return PaymentToken.DAI;
    case "3":
      return PaymentToken.USDC;
    case "4":
      return PaymentToken.USDT;
    case "5":
      return PaymentToken.TUSD;
    default:
      return PaymentToken.DAI;
  }
};

// In this example, let's imagine we've read Lending collection data
// from a Sylvester subgraph. Here's how we'd transform the low-level
// blockchain data into high-level, human (and feline) friendly types.
const lendingsDataToLendings = (
  theGraphLendings: TheGraphLending[]
) => {
  const theGraphToLending = (theGraphLending: TheGraphLending) => {
    return {
      lendingID: theGraphLending.id,
      lenderAddress: theGraphLending.lenderAddress,
      // Convert the price back into a BigNumber.
      dailyRentPrice: unpackPrice(theGraphLending.dailyRentPrice),
      maxRentDuration: Number(theGraphLending.maxRentDuration),
      lendAmount: Number(theGraphLending.lendAmount),
      paymentToken: parsePaymentToken(theGraphLending.paymentToken),
      lentAt: Number(theGraphLending.lentAt),
    };
  };

  return theGraphLendings.map(theGraphToLending);
};
```


# Castle Crush (Reward Share)

This is a guide on how to the reNFT's SDK to interact with our Reward Share contracts.

> This tutorial was written for SDK version `6.0.0`.

The reNFT SDK is written in TypeScript. You can install the SDK by running `yarn add @renft/sdk` from your Command Line Interface (CLI).

In the following section, we'll talk about Whoopi; a smart contract which enables reward-sharing rental cycles for the players of [Castle Crush](https://castlecrushgame.com/) on the [Avalanche](https://www.avax.network/) network.

## Lending a Card

During a lending, the Whoopi contract takes custody of the Castle Crush NFT instead of sending it to the renter directly. This means, similarly to Sylvester, it operates using non-collateralized lending (i.e. the renter doesn't have to put up some form of deposit in case they don't feel like returning the token).

Upon creation of the lending, the NFT resides in the contract for as long as the lending is active.&#x20;

> ⚠️ If there is no active renting, the lender may choose to terminate the lending early. However, if there is an active renting, the lender must wait for it to conclude.

Since Whoopi takes custody of the NFT, lenders are required to approve the NFT for handling by the smart contract. You can find an example of how to manage the approval process [here](https://github.com/re-nft/sdk/blob/8c61b61be8c649774df332a3078b4d1267f23ad6/examples/whoopi.js#L44).&#x20;

Once a lender has authorized permission for the smart contract to trustlessly manage rentals, the lender can begin renting out various gnarly cards in their collection. In the following snippet, we'll walk through the flow of lending out two cards from Castle Crush:

```typescript
import { JsonRpcProvider } from '@ethersproject/providers';
import { parseFixed } from '@ethersproject/bignumber';
import { Wallet } from '@ethersproject/wallet';
import {
  Whoopi,
  PaymentToken,
  RESOLVERS,
  getRenftContract,
  DEPLOYMENT_WHOOPI_AVALANCHE_MAINNET_V0,
  NETWORK_RESOLVERS,
} from '@renft/sdk';

const provider = new JsonRpcProvider('https://api.avax-test.network/ext/bc/C/rpc');
const privKey = '';

const wallet = new Wallet(privKey);
await wallet.connect(provider);

const castleCrushNftAddress = "0xeA4E79F0a40A9A468a5159499b738dc6b1332447";

const whoopi = getRenftContract({
  deployment: DEPLOYMENT_WHOOPI_AVALANCHE_MAINNET_V0,
  signer: wallet,
});

const { network: { type: networkType } } = DEPLOYMENT_WHOOPI_AVALANCHE_MAINNET_V0;

// Network Resolvers define the contract addresses that various ERC-20
// tokens have been deployed to on each network. Note that not all
// ERC-20s have been deployed to every network. For cases where a token
// is missing, it will take the value of PaymentToken.SENTINEL; an
// internal value we use to represent a missing token.
const paymentTokenResolvers = NETWORK_RESOLVERS[networkType];

// Which tokenIds we'd like to rent out from our wallet.
const tokenId = [210, 200];

// ! Note that if allowedRenters is empty, you must set upfrontRentFee to
// ! a non zero value.
const upfrontRentFee = [
  parseFixed("1", paymentTokenResolvers[PaymentToken.USDC]).toString(),
  parseFixed("1", paymentTokenResolvers[PaymentToken.USDC]).toString()
];

// ! you can't use SENTINEL as a payment token, even though
// ! you don't want to set an upfront rent fee. Just use any
// ! payment token in such a case.
const paymentToken = [PaymentToken.USDC, PaymentToken.USDC];

// Which addresses get to benefit from the terms of the rental?
const revShareBeneficiaries = [
  ["0x000000045232fe75A3C7db3e5B03B0Ab6166F425", "0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE"],
  ["0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE", "0xeA4E79F0a40A9A468a5159499b738dc6b1332447"]
];

// ! portions sum cannot be 100 here. At lend, we don't know who will rent,
// ! and the renter is always a mandatory part in rev share. We are not setting
// ! the renter here at lend time. Therefore, 100 - sum(portions) is what
// ! gets eventually assigned to the renter.
const revSharePortions = [
  [50, 40], // 10% is how much the renter will get on this lending
  [90, 5] // 5% is how much ther renter will get on this lending
];

// * means 1 and 2 cycles respectively for each token being rented.
const maxRentDuration = [1, 2];

const txn = await whoopi.lend(
  castleCrushNftAddress,
  tokenId,
  upfrontRentFee,
  revShareBeneficiaries,
  revSharePortions,
  maxRentDuration,
  paymentToken,
  undefined,
  // ! uncomment this if it does not allow you to execute because it predicts that
  // ! the transaction will fail
  // { gasLimit: 1000000 }
);

const receipt = await txn.wait();
```

## Renting a Card

To initialize a rental, the renter must approve the `PaymentToken` defined in the lending to be operated by the Whoopi contract on their behalf. To enable this, check out the following example on [authorizing payment tokens](https://github.com/re-nft/sdk/blob/8c61b61be8c649774df332a3078b4d1267f23ad6/examples/whoopi.js#L90).&#x20;

Once the renter has approved the required `PaymentToken`, and they possess at least the `upfrontRentFee` amount of the token defined in the Lending to initialize a rental, they may proceed.

In the following example, let's see how a wallet with a sufficient `PaymentToken` balance may initialize the rental of two tokens that have been made available by a lending:

```typescript
const tokenId = [210, 200];
const lendingId = [3, 4];
const rentingDuration = [1, 2];

const txn = await whoopi.rent(
  castleCrushNftAddress,
  tokenId,
  lendingId,
  rentingDuration
  // { gasLimit: 1000000 }
);

const receipt = await txn.wait();
```

## Stopping a Lending

A lender may only stop a lending if there is no active renting associated with the lending. This enables renters to enjoy the full terms of their rental.

It is this property of the transaction, where a lending may only be stopped after a rental is over, why it is **vital** to set a `maxRentDuration`.

A `maxRentDuration` places an upper-limit on the maximum number of cycles that a token can be rented out for.

For example, if `maxRentDuration` is set to `3`, it would mean that anyone in the marketplace would be allowed to rent the lending for up to `3` consecutive cycles before the window of opportunity is over. As a lender, you do not need to approve anything for this process, since this is all managed autonomously on the smart contract.

Once the terms of the lending period is over, or the lending isn't actively being rented out, a lender is free to call the stop lending function:

```typescript
const tokenId = [210, 200];
const lendingId = [3, 4];

const txn = await whoopi.stopLending(
  castleCrushNftAddress,
  tokenId,
  lendingId,
  // { gasLimit: 1000000 }
);

const receipt = await txn.wait();
```

## How do rentings terminate?

Unlike our other protocols, stopping a renting is managed internally, automatically via the reNFT bot. 🤖

Renters don't have to do anything!

In fact, *only* reNFT's bot possesses the capability to terminate the rentals. It performs this operation at midnight, after the completion of each Castle Crush lending cycle. This saves on costly expensive transactions for everyone.

The bot analyzes all of the rentings once-an-hour, meaning that it is possible that it will stop the renting with up to, but not exceeding, a one hour delay. This means sometimes you'll need to be a little patient.

## Paying Rewards

Similarly to renting, a lender must ensure that the Castle Crush contract is approved to spend their ERC-20 reward token.

When paying rewards, a lender will transfer a lump sum per lending (along with the renters' addresses) and the smart contract will calculate handle the reward splitting as per the conditions of the original lending. This helps reward revenue share parties, and enforces the correct distribution of value to the pre-agreed shares on a given lending. Simple!

```typescript
const tokenId = [210, 200];
const lendingId = [3, 4];
const renterAddress = ["0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE", "0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE"];
const amountToPay = [
  parseFixed("1", RESOLVERS[RenftContracts.WHOOPI_FUJI][PaymentToken.USDC]).toString(),
  parseFixed("1", RESOLVERS[RenftContracts.WHOOPI_FUJI][PaymentToken.USDC]).toString()
];

txn = await whoopi.pay(
  castleCrushNftAddress,
  tokenId,
  lendingId,
  renterAddress,
  amountToPay,
  // { gasLimit: 1000000 }
);
receipt = await txn.wait();
```

To learn about how to query for the on-chain data in a decentralized way, you can continue reading [here](/developers/querying-renfts-on-chain-data/castle-crush-reward-share).


# @renft/sdk\@v5.0.4


# Collateral-Free Integration Guide

This is a guide on how to use reNFT's SDK to interact with the collateral free contract directly. This tutorial was written for sdk version 5.0.4.

![reNFT collateral-free contract flows](/files/18HUCzSwTvkM1RT33qJf)

> **The following discussion applies to `v5.0.4` of the SDK.**

### Lend/Rent NFTs In-App[​](https://docs.renft.io/docs/Developers/collateral-free#lendrent-nfts-in-app) <a href="#lendrent-nfts-in-app" id="lendrent-nfts-in-app"></a>

To interact with our smart contract, we'd recommend using our [SDK](https://github.com/re-nft/sdk).

The ReNFT object takes in an ethers [Signer](https://docs.ethers.io/v5/api/signer/#Signer) and an optional contract address if not using the default collateral-free contract.

```typescript
import { Sylvester } from "@renft/sdk";
const renft = new Sylvester(signer);
```

We name our contracts after famous cats. You can find the name mappings [here](/developers/renft-contracts-addresses). `Sylvester` is the code-name for the collateral free contract.

### Batching[​](https://docs.renft.io/docs/Developers/collateral-free#batching) <a href="#batching" id="batching"></a>

Any of the following functions support batching as shown below for the Lend instruction where the user lends an AstroCat and a CatPlsr in the same function call:

```typescript
import { NFTStandard, PaymentToken, packPrice } from "@renft/sdk";

const astroCatLendingArgs = [
  NFTStandard.E1155,
  "0x0db8c099b426677f575d512874d45a767e9acc3c",
  "1",
  1,
  1,
  packPrice("1"),
  PaymentToken.WETH,
];

const catPlsrLendingArgs = [
  NFTStandard.E1155,
  "0x0db8c099b426677f575d512874d45a767e9acc3c",
  "2",
  1,
  1,
  packPrice("0.5"),
  PaymentToken.WETH,
];

const lendingArgs = astroCatLendingArgs.map((value, index) => {
  return [value, catPlsrLendingArgs[index]];
});

await renft.lend(...lendingArgs);
```

### Lend <a href="#lend" id="lend"></a>

```typescript
import { NFTStandard, PaymentToken, packPrice } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendAmount = 1; // qty of the NFT to lend
const maxRentDuration = 1; // in days
const dailyRentPrice = packPrice("1");
const paymentToken = PaymentToken.WETH;

await renft.lend(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendAmount],
  [maxRentDuration],
  [dailyRentPrice],
  [paymentToken]
);
```

### Rent[​](https://docs.renft.io/docs/Developers/collateral-free#rent) <a href="#rent" id="rent"></a>

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1"; // this information is pulled from the subgraph
const rentDuration = 1; // in days
const rentAmount = 1;

await renft.rent(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
  [rentDuration],
  [rentAmount]
);
```

### Stop Rent <a href="#stop-rent" id="stop-rent"></a>

Even though no real posession of the NFT is given, the renter must signal that they have concluded "using" the NFT with this call. If the renter fails to do so, then the lender can invoke "Claim Rent" explained below, to redeem the full amount of rent. Note that "Stop Lend" will be blocked until the user calls "Claim Rent" first.[​](https://docs.renft.io/docs/Developers/collateral-free#stop-rent)

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1"; // from subgraph
const rentingID = "1"; // from subgraph

await renft.stopRent(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
  [rentingID],
);
```

### Claim Rent[​](https://docs.renft.io/docs/Developers/collateral-free#claim-rent) <a href="#claim-rent" id="claim-rent"></a>

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1";
const rentingID = "1";

await renft.claimRent(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
  [rentingID],
);
```

### Stop Lend[​](https://docs.renft.io/docs/Developers/collateral-free#stop-lend) <a href="#stop-lend" id="stop-lend"></a>

```typescript
import { NFTStandard } from "@renft/sdk";

const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1";

await renft.stopLend(
  [nftStandard],
  [nftAddress],
  [tokenID],
  [lendingID],
);
```

### Query Loan/Rental Status[​](https://docs.renft.io/docs/Developers/collateral-free#query-loanrental-status) <a href="#query-loanrental-status" id="query-loanrental-status"></a>

To learn about how to learn about the status of a particular lending / rental, read [here](/developers/querying-renfts-on-chain-data).

### Unpacking Data[​](https://docs.renft.io/docs/Developers/collateral-free#unpacking-data) <a href="#unpacking-data" id="unpacking-data"></a>

Prices are returned in a custom format (rationale for this format was to fit the lending into a single storage slot). To unpack them, use our [SDK](https://github.com/re-nft/sdk/tree/registry)'s `unpackPrice` function:

```typescript
import { PaymentToken, unpackPrice } from "@renft/sdk";

const parsePaymentToken = (tkn: string): PaymentToken => {
  switch (tkn) {
    case "0":
      return PaymentToken.SENTINEL;
    case "1":
      return PaymentToken.WETH;
    case "2":
      return PaymentToken.DAI;
    case "3":
      return PaymentToken.USDC;
    case "4":
      return PaymentToken.USDT;
    case "5":
      return PaymentToken.TUSD;
    default:
      return PaymentToken.DAI;
  }
};

const lendingsDataToLendings = (
  theGraphLendings: TheGraphLending[]
) => {
  const theGraphToLending = (theGraphLending: TheGraphLending) => {
    return {
      lendingID: theGraphLending.id,
      lenderAddress: theGraphLending.lenderAddress,
      dailyRentPrice: unpackPrice(theGraphLending.dailyRentPrice),
      maxRentDuration: Number(theGraphLending.maxRentDuration),
      lendAmount: Number(theGraphLending.lendAmount),
      paymentToken: parsePaymentToken(theGraphLending.paymentToken),
      lentAt: Number(theGraphLending.lentAt),
    };
  };

  return theGraphLendings.map(theGraphToLending);
};
```


# Castle Crush (Reward Share)

This is a guide on how to use reNFT's SDK to interact with the Wildlife contract directly. This tutorial was written for sdk version 5.0.4.

reNFT's SDK is written in Typescript, but we plan to add more languages in the future (Python and Golang, at the very least). You can install the SDK by running `yarn add @renft/sdk`.

## Lend

Wildlife contract takes custody of the Castle Crush NFT. However, the NFT does not get transferred on rent. It sits inside of the Wildlife contract for as long as the lending is active. If there is no active renting, the lender may choose to terminate the lending. However, if there is an active renting, the lender must wait for it to conclude.

Because Wildlife contract takes custody of the NFT, you will need to approve the NFT you wish to lend to be operated by the contract. You can find an example of how to do it [here](https://github.com/re-nft/sdk/blob/8c61b61be8c649774df332a3078b4d1267f23ad6/examples/whoopi.js#L44). Once you have done that, you can lend NFT(s)

```typescript
import { JsonRpcProvider } from '@ethersproject/providers';
import { parseFixed } from '@ethersproject/bignumber';
import { Wallet } from '@ethersproject/wallet';
import { Whoopi, PaymentToken, RESOLVERS, RenftContracts } from '@renft/sdk';

const provider = new JsonRpcProvider('https://api.avax-test.network/ext/bc/C/rpc');
const privKey = '';
let wallet = new Wallet(privKey);
wallet = wallet.connect(provider);

let txn;
let receipt;

const castleCrushNftAddress = "0xeA4E79F0a40A9A468a5159499b738dc6b1332447";
const whoopiAddress = "0x516775e81b0d1fC91Ec326DEd21c33728895Fc6C";
const whoopi = new Whoopi(wallet, whoopiAddress);

const tokenId = [210, 200];
// ! Note that if allowedRenters is empty, you must set upfrontRentFee to
// ! a non zero value.
const upfrontRentFee = [
  parseFixed("1", RESOLVERS[RenftContracts.WHOOPI_FUJI][PaymentToken.USDC]).toString(),
  parseFixed("1", RESOLVERS[RenftContracts.WHOOPI_FUJI][PaymentToken.USDC]).toString()
];
// ! you can't use SENTINEL as a payment token, even though
// ! you don't want to set an upfront rent fee. Just use any
// ! payment token in such a case.
const paymentToken = [PaymentToken.USDC, PaymentToken.USDC];
const revShareBeneficiaries = [
  ["0x000000045232fe75A3C7db3e5B03B0Ab6166F425", "0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE"],
  ["0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE", "0xeA4E79F0a40A9A468a5159499b738dc6b1332447"]
];
// ! portions sum cannot be 100 here. At lend, we don't know who will rent,
// ! and the renter is always a mandatory part in rev share. We are not setting
// ! the renter here at lend time. Therefore, 100 - sum(portions) is what
// ! gets eventually assigned to the renter.
const revSharePortions = [
  [50, 40], // 10% is how much the renter will get on this lending
  [90, 5] // 5% is how much ther renter will get on this lending
];
// * means 1 and 2 cycles respectively
const maxRentDuration = [1, 2];

txn = await whoopi.lend(
  castleCrushNftAddress,
  tokenId,
  upfrontRentFee,
  revShareBeneficiaries,
  revSharePortions,
  maxRentDuration,
  paymentToken,
  undefined,
  // ! uncomment this if it does not allow you to execute because it predicts that
  // ! the transaction will fail
  // { gasLimit: 1000000 }
);
receipt = await txn.wait();
```

## Rent

To rent, you must approve the payment token of the lending to be operated by the Wildlife contract. To do so, see an example [here](https://github.com/re-nft/sdk/blob/8c61b61be8c649774df332a3078b4d1267f23ad6/examples/whoopi.js#L90). Once you have done that for the amount of `upfrontRentFee` or more, you can proceed with the renting

```typescript
const tokenId = [210, 200];
const lendingId = [3, 4];
const rentingDuration = [1, 2];

txn = await whoopi.rent(
  castleCrushNftAddress,
  tokenId,
  lendingId,
  rentingDuration
  // { gasLimit: 1000000 }
);
receipt = await txn.wait();
```

## Stop Lending

A lender can only stop the lending if there is no active renting associated with the lending. This is why it is important to set a `maxRentDuration` to the maximum number of cycles that the lender is happy with. For example, if `maxRentDuration` is set to `3` it would mean that someone can come in and rent the lending for up to `3` consecutive cycles. You do not need to approve anything from the lender's side on this step, so you are free to call the stop lending function.

```typescript
const tokenId = [210, 200];
const lendingId = [3, 4];

txn = await whoopi.stopLending(
  castleCrushNftAddress,
  tokenId,
  lendingId,
  // { gasLimit: 1000000 }
)
receipt = await txn.wait();
```

## Stop Renting

This is handled by reNFT's bot and there is no need to worry about renter's doing this themselves. In fact, only reNFT's bot is able to stop the rentals. It does so at midnight after cycle-end. The bot checks all of the rentings every hour. That means that it is possible that it will stop the renting with up to but not exceeding one hour delay. Due to the indexing solution requiring payments for every query made, one hour is a good value to stick to.

## Pay Rewards

As with renting, you must ensure that the Wildlife contract is approved to operate your ERC20 reward token. Follow the link in the Rent section to see an example on how to do this. Once approved, you are able to simply send a lump sum per lending (along with the renters' addresses), the contract will then handle the reward splitting as per the conditions of the original lending (i.e. taking into account other revenue share parties and their respective shares on this particular lending)

```typescript
const tokenId = [210, 200];
const lendingId = [3, 4];
const renterAddress = ["0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE", "0x465DCa9995D6c2a81A9Be80fBCeD5a770dEE3daE"];
const amountToPay = [
  parseFixed("1", RESOLVERS[RenftContracts.WHOOPI_FUJI][PaymentToken.USDC]).toString(),
  parseFixed("1", RESOLVERS[RenftContracts.WHOOPI_FUJI][PaymentToken.USDC]).toString()
];

txn = await whoopi.pay(
  castleCrushNftAddress,
  tokenId,
  lendingId,
  renterAddress,
  amountToPay,
  // { gasLimit: 1000000 }
);
receipt = await txn.wait();
```

## Query On-chain data

To learn about how to query the on-chain data, read [here](/developers/querying-renfts-on-chain-data/castle-crush-reward-share).


# reNFT Contracts' Addresses

reNFT is chain agnostic. As such, we have contracts on a number of chains, we are using famous cats' names to refer to each one of our contracts.

| Codename     | Formal Name               | Contract Address                                                                                                                                                                                                                                                                                                                                                         |
| ------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Azrael       | EVM Collateral V0         | <p>Ethereum:</p><p> <a href="https://etherscan.io/address/0x94D8f036a0fbC216Bb532D33bDF6564157Af0cD7"><code>0x94D8f036a0fbC216Bb532D33bDF6564157Af0cD7</code></a></p>                                                                                                                                                                                                    |
| Sylvester v0 | EVM Collateral-Free V0    | <p>Goerli:</p><p><a href="https://goerli.etherscan.io/address/0xede9a15388ccd972dffbd7c3f5504345703b63b2#code"><code>0xEDe9A15388CCd972DffBD7C3F5504345703b63b2</code></a></p><p></p><p>Ethereum:</p><p><a href="https://etherscan.io/address/0xa8D3F65b6E2922fED1430b77aC2b557e1fa8DA4a"><code>0xa8D3F65b6E2922fED1430b77aC2b557e1fa8DA4a</code></a></p>                |
| Sylvester v1 | EVM Collateral-Free V1    | <p>Polygon:</p><p><br><a href="https://polygonscan.com/address/0x4e52b73aa28b7ff84d88ea3a90c0668f46043450"><code>0x4e52b73aa28b7ff84d88ea3a90c0668f46043450</code></a></p>                                                                                                                                                                                               |
| Whoopi       | EVM Reward Share (custom) | <p>Avalanche Fuji:</p><p><br><a href="https://testnet.snowtrace.io/address/0x42816fa3cb0adc3fcaded3109323c0bc19215084"><code>0x42816FA3cB0aDc3fcAdED3109323c0Bc19215084</code></a><br><br>Avalanche C-Chain:</p><p><br><a href="https://snowtrace.io/address/0x6ee495eced3a0255057667ff2685e53f54a19a65"><code>0x6Ee495ecEd3A0255057667FF2685e53f54A19A65</code></a></p> |

Resolver contracts (they map token index to contract address). We have a need for this contract, in order to tightly pack lending details into a single storage slot.

| Resolver of | Version                                          |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ----------- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Azrael      | 0                                                | <p>Ethereum:</p><p><br><a href="https://etherscan.io/address/0x945e589a4715d1915e6fe14f08e4887bc4019341"><code>0x945e589a4715d1915e6fe14f08e4887bc4019341</code></a></p>                                                                                                                                                                                                                                                                                                                                                                                  |
| Sylvester   | <p>Ethereum: 0</p><p>Goerli: 0<br>Polygon: 1</p> | <p>Ethereum (same as azrael):</p><p><br><a href="https://etherscan.io/address/0x945e589a4715d1915e6fe14f08e4887bc4019341"><code>0x945e589a4715d1915e6fe14f08e4887bc4019341</code></a><br></p><p>Goerli:</p><p><a href="https://goerli.etherscan.io/address/0xf8834327e7f3f5103954e477a32dc742a6518a9c"><code>0xF8834327e7f3f5103954E477A32dC742A6518A9C</code></a></p><p><br>Polygon:</p><p><br><a href="https://polygonscan.com/address/0x3ddc85bb768a11b0125f4ee71cfea54e54653366#code"><code>0x3ddc85bb768a11b0125f4ee71cfea54e54653366</code></a></p> |
| Whoopi      | 0                                                | <p>Avalanche Fuji:</p><p><br><a href="https://testnet.snowtrace.io/address/0x23f7f8b03baf01d5124255fe240e81bbbd3aec0d#code"><code>0x23F7F8B03BAF01D5124255fE240E81BbBd3AEc0D</code></a><br><br>Avalanche C-Chain:</p><p><br><a href="https://snowtrace.io/address/0xebfd584aac21dfeff02c3d4f308b0962610a028a#code"><code>0xEBFd584AAC21dfEFF02c3d4f308B0962610a028A</code></a></p>                                                                                                                                                                        |


# Querying reNFT's on-chain data

## Collateral Free (aka Traditional Rentals)

### Ethereum

#### Get Renters[​](https://docs.renft.io/docs/Developers/collateral-free#query-loanrental-status) <a href="#query-loanrental-status" id="query-loanrental-status"></a>

To know who the active renters of your collection are at any point in time, you should make a GraphQL API request. Here is GraphiQL playground for you. It's useful for testing out queries:

{% embed url="<https://api.studio.thegraph.com/proxy/3020/sylvester/1.0.3/graphql?query=query+CollectionRenters%28%24nftAddress%3A+Bytes%21%29+%7B%0A++rentings%28%0A++++where%3A+%7B%0A++++%09lending_%3A+%7BnftAddress%3A+%24nftAddress%7D%2C%0A++++++expired%3A+false%2C%0A++++++cursor_gt%3A+0%0A++%09%7D%2C%0A++++first%3A+1000%2C%0A++++skip%3A+0%2C%0A++++orderBy%3A+cursor%2C%0A++++orderDirection%3A+desc%0A++%29+%7B%0A++++id%0A++++cursor%0A++++renterAddress%0A++++rentedAt%0A++++rentDuration%0A++++rentAmount%0A++++lending+%7B%0A++++++nftAddress%0A++++++tokenID%0A++++%7D%0A++%7D%0A%7D>" %}
reNFT Ethereum contract's GraphiQL client
{% endembed %}

Here is what it looks like if you follow the above link:

<figure><img src="/files/YA1xCoBI8AbK7vC9iFwg" alt=""><figcaption></figcaption></figure>

To actually make calls from your client, you simply make GraphQL POST requests to the following URL: `https://api.studio.thegraph.com/query/3020/sylvester/1.0.3`

You can play around with our GraphQL API schema in the GraphiQL UI. You will notice we have information such as `lendings` as well. However, you are interested in `rentings`, so that you can pinpoint who the current renters of your NFTs are. To do so, use the following query:

```graphql
query CollectionRenters($nftAddress: Bytes!) {
  rentings(
    where: {
    	lending_: {nftAddress: $nftAddress},
        expired: false,
        cursor_gt: 0
    },
    first: 1000,
    skip: 0,
    orderBy: cursor,
    orderDirection: desc
  ) {
    id
    cursor
    renterAddress
    rentedAt
    rentDuration
    rentAmount
    lending {
      nftAddress
      tokenID
    }
  }
}
```

Let's walk through the above. You need to supply `nftAddress` parameter in this query. This is your collection's address on Ethereum (this section concerns Ethereum renters querying). We have an `expired` flag that gets set to `true` when the rentings has overrun its duration and the lender has collected their payment on our dapp. **Note** that on Ethereum, rentals can over-run their duration. In our own API that is releasing soon, we will only return you rentals that are active at a given point in time. With the above approach, however, there is an extra step you need to do to ensure rental is in fact active. We will talk about it shortly. `cursor_gt: 0` is a way to paginate, that you will only ever need if you have more than `1000` active rentals at any given point in time. The restriction on this API is that it can only return a maximum of `1000` items. That is why we have: `first: 1000`. If you have more active rentals, then you will need to paginate like this (until you retrieve all rentals):

```graphql
query CollectionRenters($nftAddress: Bytes!) {
  rentings(
    where: {
    	lending_: {nftAddress: $nftAddress},
        expired: false,
        cursor_gt: 2003
    },
    first: 1000,
    skip: 1000,
    orderBy: cursor,
    orderDirection: desc
  ) {
    id
    cursor
    renterAddress
    rentedAt
    rentDuration
    rentAmount
    lending {
      nftAddress
      tokenID
    }
  }
}
```

The most important part here is that we have changed the value of `cursor_gt: 2003`. Taken the resultset of the original query, we noticed, hypothetically that the max `cursor` value was `2003`. This now retrieves the next `1000` rentals (or however many are left). You then repeat this process as required.

Note that `id` and `cursor` are equivalent. This is your renting id, you will not need to use it, but `cursor` is `Int` so that we can easily paginate. If we were to order the `id` which is a string, we would get an incorrect ordering of items.

We are now at a stage where we can talk about what information you need to use in your application / game to enable rentals. You simply recognise the result-set you are getting from this query as renters. You get their wallet addresses by looking at the `renterAddress` field above.

Finally, a note on `expired`. As I have mentioned previously, you need to do a small extra step here. After a rental over-runs its duration (that is to say, you take `rentedAt` UTC timestamp and add `rentDuration * 24 * 60 * 60` (duration in seconds) and compare to current UTC timestamp), its `expired` is still `false`. This is because our contract requires triggering of a particular function for lender (or anyone for that matter) to invoke for them to collect the rental payments. This action emits an on-chain event that then sets `expired` to true. So, the extra step that you need to take here is to simply after having received all the rentals from the above queries, go through each one and ensure that:

`rentedAt + rentDuration * 24 * 60 * 60 > current_timestamp_in_utc`

whatever rental items you have left after applying the above filter will ensure that you have the set of currently active rentals. Note that you can also take a route of writing a bot that invokes the mentioned function for your users. This would then ensure that all the rentals you are getting from the queries above are definitively active. If you are interested in how to do this, see this [repository](https://github.com/re-nft/example-stop-rent-bot/tree/main) (we are using this bot on polygon to stop rentals for everyone).

## Polygon

TODO


# Castle Crush (Reward Share)

## Query On-chain data

We use The Graph's subgraph to index on-chain events. To obtain the Castle Crush subgraph URL reach out to the reNFT team directly. We shall not explore how to make GraphQL queries to the subgraph here. We will merely point out an important potential "gotcha". By default, the query will return at most `100` items in the return set. The maximum you can get is `1000`. To achieve this, you must add the `first: 1000` query variable and value in your query. For example,

<pre class="language-graphql"><code class="lang-graphql"><strong>query Query {
</strong>  rentings(first: 1000, orderBy: cursor, orderDirection: asc) {
    id
    cursor
    renterAddress
    rentDuration
    rentedAt
  }
}
</code></pre>

This is not all, however. If the full set of rentings exceeds `1000` items, we will miss all the other rentings. To remedy this, we must use `first` in conjunction with a where clause. For example,

```graphql
query Query {
  rentings(first: 1000, orderBy: cursor, orderDirection: asc, where: {cursor_gt: 1000}) {
    id
    renterAddress
    rentDuration
    rentedAt
  }
}
```

The above query will now pull the next `1000` items. Note that if there are more than `2000` items we are still in trouble. To pull the next `1000` you would use `first: 1000, where: {cursor_gt: 2000}.`

**PLEASE USE THIS TECHNIQUE ON EVERY QUERY YOU ARE MAKING TO THE SUBGRAPH (lendings, rentings, users).**


# Collateral-Free


# How To Lend

**How to lend your NFT collateral-free**

{% embed url="<https://www.youtube.com/watch?feature=youtu.be&v=zO503YTYMi0>" %}

1. Connect your wallet.
2. Go to [Portfolio/MyWallet](https://v2.renft.io/user/wallet) and select the NFT you would like to lend and click on it.
3. Specify all the details required to lend the NFT.&#x20;
   1. Select “Collateral-Free”
   2. Choose which payment token you would like to receive (WETH, DAI, etc.)&#x20;
   3. Specify \[Daily Price] and \[Max Rent Duration]
4. Click \[LEND] and confirm the following transactions in your wallet&#x20;
   1. Transaction 1/2: Approve the NFT token. (Only once per Collection per wallet)&#x20;
   2. Transaction 2/2: \[CONFIRM LEND] Note: You will need to have enough funds in your wallet to pay for the transaction fees and the transaction time will depend on network activity and gas settings. For more detailed information, check the status of your transaction in the respective blockchain explorer ([etherscan ](https://etherscan.io/)/ [polygonscan](https://polygonscan.com/))
5. Success! Your NFT is now available for rent. You will find it in [Portfolio/Lending](https://v2.renft.io/user/lending).
6. Pro-Tip: Under the context menu of the NFT (three little dots) you can get a Share-Link, that you can share with your fellow degens.


# How To Rent

**How to rent a collateral-free NFT**

{% embed url="<https://www.youtube.com/watch?feature=youtu.be&v=4Woyb4zwzpw>" %}

1. Click on "COLLATERAL-FREE" in the market section.
2. Click on the NFT you want to rent.
3. Enter the max duration for which you want to rent the NFT. Note: Since this is a Collateral-Free rental, you don’t need to deposit any type of collateral.
4. After specifying the rental duration, you click \[RENT NOW] and will have to perform the following actions:&#x20;
   1. Connect your wallet if you are not already connected.
   2. Transaction 1/2: \[Approve Payment Token] (this has to be done only once per token (WETH, DAI, etc.) per Wallet)&#x20;
   3. Transaction 2/2: \[Confirm Rent] Note: You will need to have enough funds in your wallet to pay for the transaction fees and the transaction time will depend on network activity and gas settings. For more detailed information, check the status of your transaction in the respective blockchain explorer ([etherscan ](https://etherscan.io/)/ [polygonscan](https://polygonscan.com/))
5. Success! You have just rented an NFT! You will find your rented NFT in [Portfolio/Renting](https://v2.renft.io/user/renting).
6. Pro-Tip: You only pay for the actual rent duration until you return the NFT and not the specified max rent duration.


# Castle Crush (Reward Share)


# How To Lend

**How to lend an NFT with reward share**

{% embed url="<https://www.youtube.com/watch?v=aJkraKEH0XY>" %}

1. Connect your wallet.
2. Go to [Portfolio/MyWallet](https://v2.renft.io/user/wallet) and select the NFT you would like to lend and click on it.
3. Specify all the details required to lend the NFT.&#x20;
   1. Reward-Split: Define how the rewards generated with the NFT will be split between Owner and Renter of the NFT. Additional Wallet addresses can be added, but this is optional.
   2. Whitelist: By adding wallet addresses in this section, you can narrow down who will be eligible to rent this NFT. This is optional.&#x20;
   3. Specify \[Payment Token], \[Upfront Amount] (One-time lump sum. Optional, if the NFT will be whitelisted), and \[Max Lend Duration] in Cycles.
4. Click \[LEND] and confirm the following transactions in your wallet&#x20;
   1. Transaction 1/2: Approve the NFT token. (Only once per Collection per wallet)&#x20;
   2. Transaction 2/2: \[CONFIRM LEND] Note: You will need to have enough funds in your wallet to pay for the transaction fees and the transaction time will depend on network activity and gas settings. For more detailed information, check the status of your transaction in the respective blockchain explorer ([snowtrace.io](https://snowtrace.io/))
5. Success! Your NFT is now available for rent. You will find it in [Portfolio/Lending](https://v2.renft.io/user/lending)
6. Pro-Tip: Under the context menu of the NFT (three little dots) you can get a Share-Link, that you can share with your fellow degens.

Note that we also support batch lending that lets you lend more than one card in a single transaction. To achieve this, tick the checkboxes on the cards you wish to lend.

For your convenience we have also recorded a video that explains how to lend.


# How To Rent

**How to rent an NFT with reward share**

{% embed url="<https://www.youtube.com/watch?v=tMwmy5KYtmQ>" %}
YouTube video explaining how to rent a Castle Crush NFT
{% endembed %}

1. Connect your wallet.
2. Click on the NFT you want to rent.
3. Enter the Rent Duration in Cycles for which you want to rent the NFT. (1 Cycle = 1 day, resets at midnight UTC)
4. After specifying the rental duration, you click \[RENT NOW] and will have to perform the following actions:&#x20;
   1. Connect your wallet if you are not already connected.&#x20;
   2. Transaction 1/2: \[Approve Payment Token] (this has to be done only once per token (WETH, DAI, etc.) per Wallet)&#x20;
   3. Transaction 2/2: \[Confirm Rent] Note: You will need to have enough funds in your wallet to pay for the transaction fees and the transaction time will depend on network activity and gas settings. For more detailed information, check the status of your transaction via [snowtrace.io](https://snowtrace.io/)
5. Success! You have just rented an NFT! The Rental will become active at midnight UTC. You will find your rented NFT in [Portfolio/Renting](https://v2.renft.io/user/renting).

**Note also that we have batch renting functionality that allows you to rent multiple cards in a single transaction. To achieve this, you must tick the checkboxes on different cards you wish to rent.**

We have also recorded a video for your convenience


# Collateralized

####


# How To Lend

**How to lend your NFT with collateral**

{% embed url="<https://www.youtube.com/watch?feature=youtu.be&v=cUYSRSANFRQ>" %}

* Connect your wallet.
* Go to [Portfolio/MyWallet](https://v2.renft.io/user/wallet) and select the NFT you would like to lend and click on it.
* Specify all the details required to lend the NFT.&#x20;
  1. Select “Collateralized”
  2. Choose which payment token you would like to receive (WETH, DAI, etc.)&#x20;
  3. Specify \[Daily Price], \[Collateral] and \[Max Rent Duration]
     1. Pro-Tip: You can use the floor price of your NFT as a guide to determine the collateral
* Click \[LEND] and confirm the following transactions in your wallet&#x20;
  1. Transaction 1/2: Approve the NFT token. (Only once per Collection per wallet)&#x20;
  2. Transaction 2/2: \[CONFIRM LEND] Note: You will need to have enough funds in your wallet to pay for the transaction fees and the transaction time will depend on network activity and gas settings. For more detailed information, check the status of your transaction in the respective blockchain explorer ([etherscan ](https://etherscan.io/)/ [polygonscan](https://polygonscan.com/))
* Success! Your NFT is now available for rent. You will find it in [Portfolio/Lending](https://v2.renft.io/user/lending).
* Pro-Tip: Under the context menu of the NFT (three little dots) you can get a Share-Link, that you can share with your fellow degens.


# How To Rent

**How to rent a collateralized NFT**

{% embed url="<https://www.youtube.com/watch?feature=youtu.be&v=jC6SOdoAT3Y>" %}

1. Click on "COLLATERALIZED" in the market section.
2. Click on the NFT you want to rent.
3. Enter the max duration for which you want to rent the NFT.&#x20;
4. After specifying the rental duration, you click \[RENT NOW] and will have to perform the following actions:&#x20;
   1. Connect your wallet if you are not already connected.
   2. Transaction 1/2: \[Approve Payment Token] (this has to be done only once per token (WETH, DAI, etc.) per Wallet)&#x20;
   3. Transaction 2/2: \[Confirm Rent] Note: You will need to have enough funds in your wallet to pay for the transaction fees and the transaction time will depend on network activity and gas settings. For more detailed information, check the status of your transaction in the respective blockchain explorer ([etherscan ](https://etherscan.io/)/ [polygonscan](https://polygonscan.com/))
5. Success! You have just rented an NFT! You will find your rented NFT in [Portfolio/Renting](https://v2.renft.io/user/renting).
6. Pro-Tip: Don't forget to return your NFT in time, otherwise you might lose your collateral.


# Returning & Defaulting

### Returning

You can return the NFT in the [Portfolio/Renting](https://v2.renft.io/user/renting) section. Click on the 'Return' button and confirm the transaction.

### Defaulting

If a Collateralized Rental is not returned within the Rent Duration, it is considered as \[Defaulted]. The NFT can not be returned anymore and the Lender can claim the collateral in [Portfolio/Lending](https://v2.renft.io/user/lending).

Be careful when deciding how much collateral you want to charge. As a general rule of thumb, consider this as the price, for which you would be willing to let your NFT go.


# Expired Rentals

How to know when a rental on reNFT has expired?

When we query for rentals on a [Subgraph](/developers/querying-renfts-on-chain-data), there are various attributes which define the time-variant rental status of a `Renting`. These attributes are: `rentedAt`, `rentDuration` and `expired`; and they are often easily misinterpreted.&#x20;

In this short section, we'll demystify the purpose of these fields.

### Expired Rentals

The `Rental` subgraph data modal possesses an `expired` property. This is used to define when a rental successfully terminated within the agreement of the rental period.

By taking a look through the[ Subgraph Mapping](https://github.com/re-nft/subgraph/blob/15554e16b0a688c66efa1e69982e3a2a1d3e44af/mappings/core.ts#L92) (which indexes high-level representations of all on-chain transactions which took place), we can see that when a rental has been claimed, the `Rental` object is marked as expired.

Conversely, [we can see](https://github.com/re-nft/subgraph/blob/15554e16b0a688c66efa1e69982e3a2a1d3e44af/mappings/core.ts#L50) the `expired` property initialized to `false` when a `Rental` is first initiated.

### Elapsed Rentals

If the current date is greater than the time the asset was rented plus the duration of the rent, the rental period has been exceeded by the renter.

This rental state can be determined programmatically by consulting the appropriate subgraph for the smart contract the rental took place on. Using GraphQL to query a subgraph, we can determine the `rentedAt` and `rentDuration` of a specific `Renting` as follows:

```graphql
{
  renting(id: "2") {
    id
    rentedAt
    rentDuration
    expired
  }
}
```

Upon this request, the subgraph will provide the caller with a `Renting` data model with the specified expiration fields included, for instance:

```json
{
  "data": {
    "renting": {
       "id": "1",
      "rentedAt": "1671617899",
      "rentDuration": "1",
      "expired": false
    }
  }
}
```

Note that there are no on-chain events for an expiration, since this would require an associated transaction.

In this regard, if we need to determine if a rental has expired off-chain, we must compute the time at which a rental expires and compare this against the current time.

Below, we outline an example implementation in TypeScript:

```typescript
const rentedAtInSeconds = Number(renting.rentedAt);
const rentDurationInDays = Number(renting.rentDuration);

const rentedAtMilliseconds = new Date(rentedAtInSeconds * 1000).getTime();
const rentDurationMilliseconds = rentDurationInDays * 24 * 60 * 60 * 1000;

const now = Date.now(); // Current time in milliseconds.

const rentingHasElapsed =
  now > rentedAtMilliseconds + rentDurationMilliseconds;
  
if (rentingHasElapsed)
  doSomethingWithElapsedRenting(renting); // Perform some app-specific handling.

```


# Team

**Nick Vale (CEO & Co-founder)**

**Naz Vavryk (CTO & Co-founder)**

**Rod Oliveira (CMO)**

**Rommert Zijlstra (Front-end lead)**

**Alec (Back-end developer)**

**Luka Krcmar (UX/UI designer)**

**Leonor Meirelles (Graphic Designer)**


# Contact

Feel free to get in touch with us if you have any questions or suggestions.

### **Links:**[​](https://docs.renft.io/docs/Getting-started/contact#links) <a href="#links" id="links"></a>

Twitter: <https://twitter.com/renftlabs>\
Discord: <https://discord.com/invite/4Ab8tknmhf>\
Telegram: <https://t.me/renftlabs>\
Medium: <https://medium.com/renftlabs>\
Opensea: <https://opensea.io/collection/renftlabs>


