# Interacting with Smart Contracts

[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>
