# Contracts and Functions

Baskets are pools of NFTs that allow users to swap their NFTs for ERC-20 tokens. Currently, Tangible Baskets only support real estate NFTs. This allows any Tangible Real Estate NFT holder (TNFT) to deposit their NFT into a basket in exchange for basket tokens, as long as their NFT is compatible.

The basket will have a deployer (aka "BasketManager") which allows users to create a unique basket. The BasketManager is the central point of the baskets and keeps an array of all existing baskets. A user can only create a basket if they hold a TNFT of that specific category/subcategory.

Baskets allow any Tangible NFT holders to deposit freely in exchange for basket tokens (as long as the TNFT is compatible). A 0.5% mint fee is applied to all Basket mint transactions.

Basket tokens can be freely redeemed whole property TNFTs, with one randomly-selected TNFT designated for redemption at a time.

## Basket

### Code

[Basket.sol](https://github.com/TangibleTNFT/baskets-foundry/blob/main/src/Basket.sol)

### Create your own

See guide on how to [create your own basket.](https://docs.tangible.store/baskets/guides#creating-a-basket)

### Read Functions

#### **getQuoteIn**

{% code overflow="wrap" fullWidth="false" %}

```javascript
function getQuoteIn(address _tangibleNFT, uint256 _tokenId) external view returns (uint256 shares);
```

{% endcode %}

Returns an amount of ERC-20 tokens you’d receive if the specified token was deposited into the basket.

* Does NOT include the amount of basket tokens subtracted for deposit fee.

#### **getQuoteOut**

{% code overflow="wrap" %}

```javascript
function getQuoteOut(address _tangibleNFT, uint256 _tokenId) external view returns (uint256 sharesRequired);// Some code
```

{% endcode %}

Returns an amount of ERC-20 tokens required if you were to redeem the specified NFT from the basket.

#### **getRentBal**

{% code overflow="wrap" %}

```javascript
function getRentBal() external view returns (uint256 totalRent);
```

{% endcode %}

Returns the unclaimed rent balance of all TNFTs inside the basket + any rent already claimed and sitting within the basket.

* Returns an amount in USD (stablecoin) with 18 decimal points

#### **getDepositedTnfts**

{% code overflow="wrap" %}

```javascript
function getDepositedTnfts() external view returns (TokenData[] memory);
```

{% endcode %}

Returns the `depositedTnfts` state array. This array contains data for every NFT stored inside the basket.

#### **getTnftsSupported**

{% code overflow="wrap" %}

```javascript
function getTnftsSupported() external view returns (address[] memory);
```

{% endcode %}

Returns the `tnftsSupported` state array. This array contains addresses for every TNFT contract address that has NFTs stored in the basket.

#### **getTokenIdLibrary**

{% code overflow="wrap" %}

```javascript
function getTokenIdLibrary(address _tnft) external view returns (uint256[] memory);
```

{% endcode %}

Returns the `tokenIdLibrary` mapped array. This array contains tokenIds for each token stored in this contract, given the TNFT contract address.

#### **getSupportedFeatures**

{% code overflow="wrap" %}

```javascript
function getSupportedFeatures() external view returns (uint256[] memory);
```

{% endcode %}

Returns the `supportedFeatures` state array. This array contains all features the basket supports and therefore all NFTs must support in order to be compatible with the basket.

#### **getSharePrice**

{% code overflow="wrap" %}

```javascript
function getSharePrice() public view returns (uint256 sharePrice);
```

{% endcode %}

Returns the USD value per basket share in 18 decimals.&#x20;

#### **getTotalValueOfBasket**

{% code overflow="wrap" %}

```javascript
function getTotalValueOfBasket() public view returns (uint256 totalValue);
```

{% endcode %}

Returns the total USD value of the basket.

* This value is calculated as the total value of all deposited NFTs + accrued rent + unclaimed rent.
* The rent value used is only updated post-rebase.

#### **isCompatibleTnft**

{% code overflow="wrap" %}

```javascript
function isCompatibleTnft(address _tangibleNFT, uint256 _tokenId) public view returns (bool);
```

{% endcode %}

Returns true if a specified token is compatible with the basket and thus can be deposited into the basket.

A token is compatible if and only if:

* It is of the same category (or “type”)
* It supports all subcategories (aka “features”) as the basket.
* It is in the same location as the basket. (i.e. “US” or “UK”)

### Write Functions

#### **depositTNFT**

{% code overflow="wrap" %}

```javascript
function depositTNFT(address _tangibleNFT, uint256 _tokenId) external returns (uint256 basketShare);
```

{% endcode %}

This method allows any user with a compatible NFT to deposit their NFT into the basket in exchange for minted basket tokens.

* Any unclaimed rent claimable from the rent manager is claimed and transferred to the depositor.
* A deposit fee is taken upon every deposit which (by default) is .5% of basket tokens.
* The basket tokens (aka “shares”) minted is calculated using the USD value of the NFT deposited.
* The token being deposited MUST be approved on the TNFT contract before executing a deposit.

#### **batchDepositTNFT**

{% code overflow="wrap" %}

```javascript
function batchDepositTNFT(address[] memory _tangibleNFTs, uint256[] memory _tokenIds) external returns (uint256[] memory basketShares);
```

{% endcode %}

This method allows any user with a 1 or more compatible NFTs to deposit a batch of NFTs into the basket in exchange for minted basket tokens.

* Any unclaimed rent claimable from the rent manager is claimed and transferred to the depositor.
* A deposit fee is taken upon every deposit which (by default) is .5% of basket tokens.
* The basket tokens (aka “shares”) minted is calculated using the USD value of the NFTs deposited taking into account the native share price.
* The tokens being deposited MUST be approved on the TNFT contract(s) before executing a batch deposit.

#### **redeemTNFT**

{% code overflow="wrap" %}

```javascript
function redeemTNFT(uint256 _budget, bytes32 _desiredToken) external;
```

{% endcode %}

This method is used to redeem an NFT from the basket in exchange for basket tokens. This method will take a budget of basket tokens and your desired token data (NFT contract address + tokenId) and if the budget is sufficient will transfer the NFT stored in `nextToRedeem` to the msg.sender.

* The NFT stored in `nextToRedeem` is randomly chosen via VRF.
* After a successful execution of this method, a new \*random\* NFT will be chosen.
* The basket tokens (aka “shares”) burned are calculated using the USD value of the NFTs deposited taking into account the native share price.

#### **rebase**

{% code overflow="wrap" %}

```javascript
function rebase() public;
```

{% endcode %}

This function allows for the Basket token to "rebase" and will update the rebase multiplier (aka “rebaseIndex”) based on the amount of rent accrued by the basket tokens.

* As the amount of rent accrued increases, every balance of basket token holders will also increase.
* 10% of the incoming rent is distributed to veRWA holders.

## BasketManager

### Code

[BasketManager.sol](https://github.com/TangibleTNFT/baskets-foundry/blob/main/src/BasketManager.sol)

### Address

`0x5e581ce0472bF528E7F5FCB96138d7759AC2ac3f`

### Read Functions

#### **getBasketsArray**

{% code overflow="wrap" %}

```javascript
function getBasketsArray() external view returns (address[] memory);
```

{% endcode %}

Returns an array of basket addresses that have been deployed.

#### fetchBasketByHash

{% code overflow="wrap" %}

```javascript
function fetchBasketByHash(bytes32 _featuresHash) public view returns (address);
```

{% endcode %}

Returns the address associated with a features hash. If address(0), hash is not taken.

* A hash is consisted of 3 things:
  * tnftType of basket as uint256
  * location ISO code as uint16
  * array of features as uint256

#### **createHash**

{% code overflow="wrap" %}

```javascript
function createHash(uint256 _tnftType, uint16 _location, uint256[] memory _features) public pure returns (bytes32 hashedFeatures);
```

{% endcode %}

Takes the 3 arguments that create a unique basket and creates a 32 byte hash. The 3 arguments are mentioned above.

### Write Functions

#### **deployBasket**

{% code overflow="wrap" %}

```javascript
function deployBasket(
    string memory _name,
    string memory _symbol,
    uint256 _tnftType,
    uint16 _location,
    uint256[] memory _features,
    address[] memory _tangibleNFTDeposit,
    uint256[] memory _tokenIdDeposit
) external returns (IBasket, uint256[] memory basketShares);
```

{% endcode %}

This method deploys a new Basket contract.

* The combination of `_tnftType`, `_location`, and `_features` MUST be unique.
* The `_name` must be unique
* The `_symbol` must be unique
* 1 or more compatible NFTs must be specified as the initial deposit.
* `_features` must be sorted and cannot contain duplicates.

This method returns the address of the new basket as well as the array of basket tokens minted to the deployer.

## BasketVrfConsumer

### Code

[BasketsVrfConsumer.sol](https://github.com/TangibleTNFT/baskets-foundry/blob/main/src/BasketsVrfConsumer.sol) inherits `GelatoVRFConsumerBaseUpgradeable`

### Address

`0x68179D8f2dbd5969F421DfC5f92C40ecDD530c41`

### Read Functions

#### **requestTracker**

{% code overflow="wrap" %}

```javascript
function requestTracker(uint256) public view returns (address);
```

{% endcode %}

Returns the address of a basket that made the VRF request, given the requestId.

#### **outstandingRequest**

```javascript
function outstandingRequest(address) public view returns (uint256);
```

Returns the outstanding requestId for a specified basket’s pending request for entropy, if any.

### Write Functions

#### **makeRequestForRandomWords**

```javascript
function makeRequestForRandomWords() external onlyBasket returns (uint256 requestId);
```

This method makes a request to Gelato VRF. It will return with a valid requestId provided by Gelato.

* Only callable by a basket contract.

#### **fulfillRandomWords**

{% code overflow="wrap" %}

```javascript
function fulfillRandomness(uint256 randomness, bytes calldata dataWithRound) external;
```

{% endcode %}

This method is the VRF callback function. Vrf coordinator will respond with our random word by calling this method.

* Only callable by the VRF coordinator contract.
* Will make an external call to the appropriate basket awaiting entropy. Will be used to generate the next redeemable NFT in that basket.
