# Collateral-Free Integration Guide

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

![reNFT collateral-free contract flows](https://3102760751-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHx6VlzrcQxjsYD9J3le4%2Fuploads%2Fp13K2RZ1M10oY3AJb47S%2F220719_Up-Front%20Payment_Info.png?alt=media\&token=24c726c5-e3ec-4004-b58c-13f43d465454)

### 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](https://docs.renft.io/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](https://docs.renft.io/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);
};
```
