# Introduction

## Introduction to Unlockd

Unlockd is a decentralized, non-custodial liquidity protocol that allows users to participate as depositors or borrowers. It is primarily composed of smart contracts deployed on the Ethereum Mainnet, enabling depositors to provide liquidity with ERC20 tokens and earn passive income. Borrowers, on the other hand, can obtain overcollateralized loans by using their non-fungible ERC721 assets as collateral.&#x20;

This document provides essential information about the smart contracts used in the Unlockd protocol and an overview of its primary use cases.&#x20;

By following the guidelines and understanding the use cases outlined, developers can effectively interact with the smart contract functions and participate in Unlockd's decentralized liquidity protocol.

## Risk Framework

At Unlockd, we understand the potential risks of market volatility and how it can affect the&#x20;

Unlockd acknowledges the potential risks associated with market volatility and continuously seeks ways to improve the protocol's safety and reliability. The Unlockd Risk Framework outlines key risks and the mitigation strategies implemented to address them.

<br>

## Contract interactions and use cases

### Deposit

Users can deposit ERC-20 tokens into the protocol using the `deposit()` function in the `LendPool.sol` contract. The deposited assets are added to the protocol's reserves, and the user receives uTokens representing their deposit position. The user must provide the asset, the deposit amount, and the address that will receive the uTokens.

### Withdraw

Users can withdraw their deposited assets using the `withdraw()` function in the `LendPool`. The equivalent uTokens are burned, and the original asset is returned to the user. The user must specify the asset, withdrawal amount, and the address that will receive the underlying assets.

### Borrow

The Unlockd protocol enables users to borrow against their NFT assets by using them as collateral. Each NFT collateral is associated with a single loan containing all relevant borrow position data. The user must specify the asset, the borrow amount, the collateral's collection address and token ID, and the loan receiver's address.

### Repay

Users must repay over-collateralized loans, including a small fee. The `repay()` function in the `LendPool` facilitates loan repayment and the return of the collateralized NFT. Users must provide the NFT's collection address and token ID, as well as the repayment amount. Partial repayments are allowed, e.g., to improve a user's health factor.

### Redeem

If a user's health factor drops below 1, an auction process is triggered. The NFT collateral owner can redeem the NFT loan by repaying the debt and an additional bid fine as a penalty for triggering the auction. The user must specify the NFT's collection address and token ID, the repayment amount, and the bid fine.

### Buyout

During an auction, users can perform a buyout if the health factor is below 1. The user pays the NFT's appraised value, not the debt amount, and becomes the new owner upon transaction completion.

### Liquidate

Liquidation occurs when a non-fungible asset used as collateral in the protocol reaches a health factor value below 1. An external server monitors all the protocol loans and identifies unhealthy loans. When an unhealthy loan is detected, the NFT can be put up for auction. The auction process starts with Unlockd setting a minimum bid price equal to the debt. A duration is established for the auction, and users can place bids above the minimum price or the previous highest bid (the first bid benefits from a return fee to incentivize bidding). Two scenarios may arise when an auction is triggered:

* If bids are placed, the NFT is sold to the highest bidder, including the available price from Reservoir, and the highest amount is used to liquidate the NFT, allowing the protocol to recover the loaned amount.
* If no bids are placed, the NFT is liquidated through the Reservoir adapter. An external server monitors the auction duration and triggers the Reservoir sale by accepting the highest offer available in the market, as provided by Reservoir.


# Overview

<figure><img src="https://2810880418-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FI7CtufywvWjm7Lk0Eaes%2Fuploads%2FNjZI2aVW9BJEzaNZK72M%2Fgitbook1.png?alt=media&amp;token=beedb324-5383-4765-8ee8-4236991b887d" alt=""><figcaption></figcaption></figure>

## Main contracts

{% hint style="info" %}
Both `LendPoolAddressesProvider` and `LendPoolAddressesProviderRegistry` control the upgradeability of the protocol, including asset listings and changes to protocol parameters. Unlockd token holders govern both contracts through the Unlockd Protocol Governance.
{% endhint %}

The primary contracts in Unlockd and their purposes are:

### LendPool

The LendPool contract is the main entry point into the Unlockd Protocol. Most interactions with Unlockd will happen via the LendPool, including the following functions:

* [deposit() ](/unlockd-for-devs-v1/the-core-protocol/lendpool#deposit)
* [withdraw()](/unlockd-for-devs-v1/the-core-protocol/lendpool#withdraw)
* [borrow()](/unlockd-for-devs-v1/the-core-protocol/lendpool#borrow)
* [repay()](/unlockd-for-devs-v1/the-core-protocol/lendpool#repay)
* [auction()](https://devs.unlockd.finance/unlockd-for-devs-v1/)
* [buyout()](/unlockd-for-devs-v1/the-core-protocol/lendpool#buyout)
* [redeem()](/unlockd-for-devs-v1/the-core-protocol/lendpool#redeem)
* [liquidate()](https://devs.unlockd.finance/unlockd-for-devs-v1/)

### LendPoolAddressesProvider

The \`LendPoolAddressesProvider\` contract serves as the main addresses register of the protocol. Developers should retrieve the latest contract addresses from this contract by making the appropriate calls.

### LendPoolAddressesProviderRegistry

This contract contains a list of `LendingPoolAddressProvider` addresses.

### uTokens

uTokens are the yield-generating, tokenized deposits used throughout the Unlockd protocol. They implement most of the standard EIP-20/ERC20 token methods with slight modifications, as well as Unlockd-specific methods, including:

* `scaledBalanceOf()`
* `getScaledUserBalanceAndSupply()`
* `scaledTotalSupply()`
* `mintToTreasury()`
* `transferUnderlyingTo()`

### Debt Tokens

Debt Tokens are the tokenized borrow positions used throughout the Unlockd protocol. Most standard EIP-20/ERC20 methods are disabled since debt tokens are non-transferable.

For more information, refer to the [Debt Tokens](/unlockd-for-devs-v1/the-core-protocol/debt-tokens) section.

## Supporting contracts

These contracts should generally not be interacted with directly but are used throughout the Unlockd Protocol via contract calls.

### LendPool Configurator

The LendPool Configurator contract provides configuration functions for the `LendPool` contracts. It also has several important functions:

* Activating / Deactivating reserves
* Enabling / Disabling borrowing for an NFT
* Enabling / Disabling using an NFT as collateral
* Freezing / Unfreezing reserves
* Updating a reserve's decimals
* Updating an NFT's Loan to Value (LTV)
* Updating an NFT's liquidation threshold
* Updating an NFT's liquidation bonus
* Updating an NFT's redeem duration
* Updating an NFT's auction duration
* Updating an NFT's min bid fine
* Updating a reserve's interest rate strategy address
* Activating / Deactivating all functions of a LendPool in emergencies

For all the above functions, relevant events are emitted on the blockchain. Developers can monitor these events to track changes in values or when values have been added or removed.

### Interest Rate Strategy

The Interest Rate Strategy contract holds the information needed to calculate and update the interest rates of specific reserves. Each contract stores the optimized base curves using the corresponding parameters of each currency. There is a mathematical function that determines the interest rate of each asset pool, with the interest rate changing based on the amount of borrowed funds and the total liquidity (i.e., utilization) of the asset pool.

The parameters for the optimized base curves are:

* `baseVariableBorrowRate`
* `variableRateSlope1`
* `variableRateSlope2`
* `stableRateSlope1`
* `stableRateSlope2`

The interest rates are calculated depending on the available liquidity and the total borrowed amount.

### Reserve Price Oracle Provider

The Reserve Price Oracle Provider contract provides reserve price data required throughout the Unlockd protocol, using Chainlink. More details can be found on the [Reserve Oracle](/unlockd-for-devs-v1/the-core-protocol/reserve-oracle) page.

### NFT Price Oracle Provider

The `NFT Price Oracle Provider` contract provides NFT price data required throughout the Unlockd protocol, using Upshot. Prices are monitored externally by the Unlockd team. More details can be found on the [NFT Oracle](/unlockd-for-devs-v1/the-core-protocol/nft-oracle) page.


# LendPool

lendpool.sol

The `LendPool` contract is the main contract of the protocol. It exposes all the user-oriented actions that can be invoked using either Solidity or web3 libraries.

The source code can be found on [GitHub](https://github.com/UnlockdFinance/unlockd-protocol-v1/blob/master/contracts/protocol/LendPool.sol) here\*\*.\*\*

{% hint style="info" %}
LendPool methods deposit, withdraw, triggerUserCollateral, borrow, repay, auction, redeem, liquidate, and liquidateNFTX are only for ERC20 and ERC721.\
If you want to deposit, withdraw, triggerUserCollateral, borrow, repay, auction, or redeem using native ETH, use WETHGateway instead.\
If you want to borrow or repay using CryptoPunks as collateral, use PunkGateway.
{% endhint %}

## View Methods

### getReserveConfiguration

`function getReserveConfiguration(address asset) external view override returns (DataTypes.ReserveConfigurationMap memory)`

Returns the configuration of the reserve.

#### Call Params

| Name  | Type    | Description                                 |
| ----- | ------- | ------------------------------------------- |
| asset | address | the address of the underlying asset (ERC20) |

#### Return Values

| Type                              | Description                                                                                                                                                                                                                                                                                             |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DataTypes.ReserveConfigurationMap | <p>The reserve configuration values are stored on-chain: <br>LTV, </p><p>Liq. threshold,</p><p>Liq. bonus,</p><p>Decimals,</p><p>Reserve is active,</p><p>Reserve is frozen,</p><p>Borrowing is enabled, </p><p>Stable rate borrowing enabled, </p><p>Reserved, </p><p>Reserve factor uint256 data;</p> |

### getNftConfigByTokenId

`function getNftConfigByTokenId(address asset, uint256 nftTokenId) external view override returns (DataTypes.NftConfigurationMap memory)`

Returns the configuration of the NFT collection as a default config.&#x20;

{% hint style="info" %}
Each NFT has its own configuration by`tokenId`, not by collection.
{% endhint %}

#### Call Params

| Name       | Type    | Description                                  |
| ---------- | ------- | -------------------------------------------- |
| asset      | address | the address of the underlying asset (ERC721) |
| nftTokenId | uint256 | the tokenId of the underlying asset (ERC721) |

#### Return Values

| Type                          | Description                                                                                                                                                                                                                                                                                   |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DataTypes.NftConfigurationMap | <p>The reserve configuration values are stored on-chain: <br>LTV, </p><p>Liq. threshold,</p><p>Liq. bonus,</p><p>NFT is active,</p><p>NFT is frozen,</p><p>Redeem duration,</p><p>Auction duration,</p><p>Redeem fine,</p><p>Redeem threshold</p><p>Min bid fine,</p><p>timestamp config;</p> |

### getReserveNormalizedIncome

`function getReserveNormalizedIncome(address asset) external view override returns (uint256)`

Returns the normalized income of the reserve.

#### Call Params

| Name  | Type    | Description                                 |
| ----- | ------- | ------------------------------------------- |
| asset | address | the address of the underlying asset (ERC20) |

#### Return Values

| Type    | Description               |
| ------- | ------------------------- |
| uint256 | normalized income amount. |

### getReserveNormalizedVariableDebt

`function getReserveNormalizedVariableDebt(address asset) external view override returns (uint256)`

Returns the normalized variable debt per unit of asset.

#### Call Params

|       |         |                                             |
| ----- | ------- | ------------------------------------------- |
| asset | address | the address of the underlying asset (ERC20) |

#### Return Params

| Type    | Description                     |
| ------- | ------------------------------- |
| uint256 | normalized variable debt amount |

### getReserveData

`function getReserveData(address asset) external view override returns (DataTypes.ReserveData memory)`

Returns the state and configuration of the reserve.

#### Call Params

| Name  | Type    | Description                                 |
| ----- | ------- | ------------------------------------------- |
| asset | address | the address of the underlying asset (ERC20) |

#### Return Values

| Type                    | Description                                                                                                                                                                                                                                                                                                  |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `DataTypes.ReserveData` | <p>The reserve data struct</p><p>ReserveConfigurationMap configuration, </p><p>liquidityIndex, </p><p>variableBorrowIndex, </p><p>currentLiquidityRate, </p><p>currentVariableBorrowRate, </p><p>lastUpdateTimestamp,</p><p>uTokenAddress,</p><p>debtTokenAddress, </p><p>interestRateAddress,</p><p>id;</p> |

### getNftData

`function getNftData(address asset) external view override returns (DataTypes.NftData memory)`

Returns the state and configuration of the NFT.

#### Call Params

| Name  | Type    | Description                                  |
| ----- | ------- | -------------------------------------------- |
| asset | address | the address of the underlying asset (ERC721) |

#### Return Values

| Type                | Description                                                                                                                                  |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `DataTypes.NftData` | <p>Returns the NFT data Struct:</p><p>NftConfigurationMap configuration,</p><p>uNftAddress,</p><p>id,</p><p>maxSupply,</p><p>maxTokenId;</p> |

### getNftCollateralData

`function getNftCollateralData(address nftAsset, uint256 nftTokenId, address reserveAsset) external view override returns (uint256 totalCollateralInETH, uint256 totalCollateralInReserve, uint256 availableBorrowsInETH,  uint256 availableBorrowsInReserve, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus)`

Returns the loan data of the NFT by TokenId.

#### Call Params

| Name         | Type    | Description                                         |
| ------------ | ------- | --------------------------------------------------- |
| nftAsset     | address | the address of the underlying asset (ERC721)        |
| nftTokenId   | uint256 | the tokenId of the underlying asset                 |
| reserveAsset | address | the address of the underlying reserve asset (ERC20) |

#### Return Values

| Name                      | Type    | Description                                |
| ------------------------- | ------- | ------------------------------------------ |
| totalCollateralInETH      | uint256 | the total collateral in ETH of the NFT     |
| totalCollateralInReserve  | uint256 | the total collateral in Reserve of the NFT |
| availableBorrowsInETH     | uint256 | the borrowing power in ETH of the NFT      |
| availableBorrowsInReserve | uint256 | the borrowing power in Reserve of the NFT  |
| ltv                       | uint256 | loan to value for the NFT/User             |
| liquidationThreshold      | uint256 | the liquidation threshold of the NFT       |
| liquidationBonus          | uint256 | the liquidation bonus of the NFT           |

### getNftDebtData

`function getNftDebtData(address nftAsset, uint256 nftTokenId) external view override returns (uint256 loanId, address reserveAsset, uint256 totalCollateral, uint256 totalDebt, uint256 availableBorrows, uint256 healthFactor)`

Returns the debt data of the NFT.

#### Call Params

| Name       | Type    | Description                                  |
| ---------- | ------- | -------------------------------------------- |
| nftAsset   | address | the address of the underlying asset (ERC721) |
| nftTokenId | uint256 | the tokenId of the underlying asset          |

#### Return Values

| Name             | Type    | Description                          |
| ---------------- | ------- | ------------------------------------ |
| loanId           | uint256 | the loan id of the NFT               |
| reserveAsset     | address | the address of the Reserve           |
| totalCollateral  | uint256 | the total power of the NFT           |
| totalDebt        | uint256 | the total debt of the NFT            |
| availableBorrows | uint256 | the borrowing power left of the NFT  |
| healthFactor     | uint256 | the current health factor of the NFT |

### getNftAuctionData

`function getNftAuctionData(address nftAsset, uint256 nftTokenId) external view override returns (uint256 loanId, address bidderAddress, uint256 bidPrice, uint256 bidBorrowAmount, uint256 bidFine)`

Returns the auction data of the NFT.

#### Call Params

| Name       | Type    | Description                                  |
| ---------- | ------- | -------------------------------------------- |
| nftAsset   | address | the address of the underlying asset (ERC721) |
| nftTokenId | uint256 | the tokenId of the underlying asset          |

#### Return Values

| Name            | Type    | Description                                         |
| --------------- | ------- | --------------------------------------------------- |
| loanId          | uint256 | the loan id of the NFT                              |
| bidderAddress   | address | the highest bidder address of the loan              |
| bidPrice        | uint256 | the highest bid price in Reserve of the loan        |
| bidBorrowAmount | uint256 | the borrow amount in Reserve of the loan            |
| bidFine         | uint256 | the penalty fine of the loan paid to the 1st bidder |

### getReservesList

`function getReservesList() external view override returns (address[] memory)`

Returns the list of the initialized reserves.

#### Return Values

| Type                          | Description                                 |
| ----------------------------- | ------------------------------------------- |
| array of address (address\[]) | A list of address, the initialized reserves |

### getNftsList

`function getNftsList() external view override returns (address[] memory)`

Returns the list of the initialized NFTs.

#### Return Values

| Type                          | Description                                     |
| ----------------------------- | ----------------------------------------------- |
| array of address (address\[]) | A list of address, the initialized NFT reserves |

## Write Methods

### deposit

`function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external override nonReentrant whenNotPaused`

Deposit the user-chosen amount of a certain `asset` into the protocol, minting the same `amount` of corresponding uTokens, and transferring them to the `onBehalfOf` address.

Example: Bob deposits 100 WETH and will get 100 uWETH in return as proof of the deposited amount.

{% hint style="danger" %}
The referral program is coded but inactive. You can pass a 0 as `referralCode.`
{% endhint %}

{% hint style="warning" %}
When depositing, the `LendPool` contract must have`allowance()`**to spend funds on behalf of**`msg.sender` for at least the`amount of` the **`asset`** being deposited.\
This can be done via the standard ERC20 `approve()` method.
{% endhint %}

#### Call Params

| Name         | Type    | Description                                                                                                                 |
| ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| asset        | address | the address of the underlying asset (ERC20)                                                                                 |
| amount       | uint256 | the amount to deposit expressed in wei units                                                                                |
| onBehalfOf   | address | <p>address whom will receive the uTokens.<br>Use <code>msg.sender</code> when the uTokens should be sent to the caller.</p> |
| referralCode | uint16  | the referral program is not working at the moment use 0                                                                     |

### withdraw

`function withdraw(address asset, uint256 amount, address to) external override nonReentrant whenNotPaused returns (uint256)`

Withdraws the amount of the underlying `asset` based on the `amount` of uTokens being held and burns the same amount of uTokens.

Example: Bob withdraws 10 ETH. Bob will get 10 ETH and will burn the same amount in uTokens.

{% hint style="warning" %}
When withdrawing `to` another address, the `msg.sender`should hold enough uTokens that the lendPool will burn.
{% endhint %}

#### Call Params

| Name   | Type    | Description                                      |
| ------ | ------- | ------------------------------------------------ |
| asset  | address | address of the underlying asset (ERC20)          |
| amount | uint256 | the amount to be withdraw expressed in wei units |
| to     | address | the address that will receive the asset.         |

#### Return Params

| Type    | Description                   |
| ------- | ----------------------------- |
| uint256 | the amount that was withdrawn |

### approveValuation

`function approveValuation(address nftAsset, uint256 nftTokenId) external payable override onlyHolder(nftAsset, nftTokenId) whenNotPaused`

This will ensure that the user holds the `nftAsset` or the uNFT version of it (ERC721). It will charge a small fee to the user to configure his NFT on the protocol.

{% hint style="info" %}
This function needs to be done before borrowing. Otherwise, it will revert.
{% endhint %}

#### Call Params

| Name       | Type    | Description                                                |
| ---------- | ------- | ---------------------------------------------------------- |
| nftAsset   | address | the adress of the underlying NFT asset used as collateral  |
| nftTokenId | uint256 | the TokenId of the underlying NFT asset used as collateral |

### borrow

`function borrow(address asset, uint256 amount, address nftAsset, uint256 nftTokenId, address onBehalfOf, uint16 referralCode) external override nonReentrant whenNotPaused`

The user will be able to borrow an `amount` of `asset` using his `nftAsset` as collateral to a wallet `onBehalfOf` and will also receive the same `amount` in debt tokens as proof of debt.

Example: Alice borrows 10 ETH using her Lockey NFT with tokenid 1.\
Alice will lock her NFT and get a uNFT (wrapped version of the collateral), debt tokens representing her debt to the protocol and the 10 ETH.

{% hint style="danger" %}
The referral program is coded but inactive. You can pass a 0 as `referralCode.`
{% endhint %}

{% hint style="warning" %}
The borrowing can only be done if your NFT is configured on the protocol.

To do this, the triggerUserCollateral needs to be called first.\
Also, there's a `_timeFrame` variable configured that will validate the time between configuring the NFT and the borrow. If the time is exceeded, it will revert.\\

The `_timeFrame` can be checked with `getTimeframe()`
{% endhint %}

#### Call Params

| Name         | Type    | Description                                                                                                                                                 |
| ------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| asset        | address | The address of the underlying asset to borrow                                                                                                               |
| amount       | uint256 | the amount to be borrowed expressed in wei units                                                                                                            |
| nftAsset     | address | the address of the underlying NFT used as collateral                                                                                                        |
| nftTokenId   | uint256 | the tokenId of the underlying NFT used as collateral                                                                                                        |
| onBehalfOf   | address | <p>address whom will receive the borrowed amount.<br>Use <code>msg.sender</code> when the debt tokens and borrowed amount should be sent to the caller.</p> |
| referralCode | uint16  | the referral program is not working at the moment use 0                                                                                                     |

### repay

`function repay(address nftAsset, uint256 nftTokenId, uint256 amount) external override nonReentrant whenNotPaused returns (uint256, bool)`

Repays a borrowed `amount` equal to or less than the amount owed from the specified collateral, `nftAsset`. It will burn the same `amount` of `debt tokens`.

Example: Alice decides to pay 2 ETH from the borrowed amount. Alice will use her uNFT to identify the loan, will give 2 ETH and will burn the same amount in debt tokens.

#### Call Params

| Name       | Type    | Description                                    |
| ---------- | ------- | ---------------------------------------------- |
| nftAsset   | address | the underlying NFT address used as collateral  |
| nftTokenId | uint256 | the underlying NFT token Id used as collateral |
| amount     | uint256 | the amount that the user wants to repay        |

#### Return Values

| Type    | Description                                                                |
| ------- | -------------------------------------------------------------------------- |
| uint256 | the repayed amount                                                         |
| bool    | will return true if the total amount is repaid or false if partially paid. |

### auction

`function auction(address nftAsset, uint256 nftTokenId, uint256 bidPrice, address onBehalfOf) external override nonReentrant whenNotPaused`

When the health factor is below one, the users can trigger an auction if they want to buy the collateral asset, the NFT used in the loan. The `bidPrice` needs to be higher than

When a user bids, the money gets locked on the contract till someone outbids or the liquidation happens.

Example: Alice's NFT price went down, and the health factor (HF) went below 1. Bob, that loves the Lockeys decide to bid.\
If there's a second bid, the first bidder will get a 2.5% bidFine for being the first. The bidFine will also be paid if Alice decides to redeem part of the debt and make the HF go above one.

| Name       | Type    | Description                                                                                            |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------ |
| nftAsset   | address | the underlying NFT address used as collateral with HF < 1                                              |
| nftTokenId | uint256 | the underlying NFT token Id used as collateral with HF < 1                                             |
| bidPrice   | uint256 | the amount that the msg.sender decides to bid needs to be higher than previous or the debt amount + 1% |
| onBehalfOf | address | address whom will receive the NFT in case the auction is successful                                    |

### redeem

`function redeem(address nftAsset, uint256 nftTokenId, uint256 amount, uint256 bidFine) external override nonReentrant whenNotPaused returns (uint256)`

Redeem should be used by the NFT Owner in case the NFT goes into auction and he wants to keep his NFT.

{% hint style="info" %}
If the auction starts and the redeem duration are still available, the user can pay an amount to increase the Health Factor.

The amount needs to be higher than the `(borrowAmount * redeemThreshold)/100`
{% endhint %}

Example: Alice's NFT was bid by Bob, but since Alice can still redeem, she decides to pay 70% of her debt to get the Health Factor > 1.

#### Call Params

| Name       | Type    | Description                                                                                              |
| ---------- | ------- | -------------------------------------------------------------------------------------------------------- |
| nftAsset   | address | the underlying NFT address used as collateral with HF < 1 and `redeemDuration` available                 |
| nftTokenId | uint256 | the underlying NFT token Id used as collateral with HF < 1 and `redeemDuration` available                |
| amount     | uint256 | the amount that NFT Owner decides to pay                                                                 |
| bidFine    | uint256 | the 2.5 fee the user needs to pay to the first bidder in case someone bidded during the `redeemDuration` |

#### Return Values

| Type    | Description           |
| ------- | --------------------- |
| uint256 | paid amount + bidFine |

### Liquidate

`function liquidate(address nftAsset, uint256 nftTokenId, uint256 amount) external override nonReentrant whenNotPaused returns (uint256)`

After the auction period ends. The liquidator should trigger this so he can receive his collateral asset.

Example: Bob wins the auction. He can call this function to get his collateral (NFT) into his wallet.

#### Call Params

| Name       | Type    | Description                                                             |
| ---------- | ------- | ----------------------------------------------------------------------- |
| nftAsset   | address | the underlying NFT address used as collateral and bought on an auction  |
| nftTokenId | uint256 | the underlying NFT token Id used as collateral and bought on an auction |
| amount     | uint256 | the auction amount used to buy the NFT.                                 |

#### Return Values

| Type    | Description               |
| ------- | ------------------------- |
| uint256 | `borrowAmount - bidPrice` |

### Buyout

```
function buyout(address nftAsset, uint256 nftTokenId, 
address onBehalfOf) external override nonReentrant whenNotPaused
```

If the health factor of the NFT falls below one, an auction will be initiated. The minimum bid amount during the auction will be the same as the debt amount. Users will have the option to buyout the NFT during the auction by clicking on the buyout button.\
\
The buyout amount of the NFT will be calculated on the smart contract and will be the highest value between the NFT valuation and its debt. To enable this function, the "approve" function to spend WETH will need to take into consideration the buyout amount.

#### Call Params

| Name       | Type    | Description                                                             |
| ---------- | ------- | ----------------------------------------------------------------------- |
| nftAsset   | address | the underlying NFT address used as collateral and bought on an auction  |
| tokenId    | uint256 | the underlying NFT token Id used as collateral and bought on an auction |
| onBehalfOf | address | The address that will receive the NFT                                   |


# LendPoolLoan

LendPoolLoan.sol

The LendPoolLoan is called by the LendPool and does everything related to loans and collaterals.

## View Methods

`function borrowerOf(uint256 loanId) external view returns (address)`

Returns the address of the borrower.

#### Call Params

| Name   | Type    | Description        |
| ------ | ------- | ------------------ |
| loanId | uint256 | the id of the loan |

#### Return Values

| Type    | Description                                         |
| ------- | --------------------------------------------------- |
| address | the `borrower` address associated with the `loanId` |

### getCollateralLoanId

`function getCollateralLoanId(address nftAsset, uint256 nftTokenId) external view returns (uint256)`

&#x20;Returns the loan id corresponding to a specific `nftAsset` and `nftTokenId`

#### Call Params

| Name       | Type    | Description                          |
| ---------- | ------- | ------------------------------------ |
| nftAsset   | address | The address of the underlying asset. |
| nftTokenId | uint256 | the tokenId of the underlying asset  |

#### Return Values

| Name    | Description                       |
| ------- | --------------------------------- |
| uint256 | the loan Id for the specified NFT |

### getLoanIdTracker

`function getLoanIdTracker() external view returns (struct CountersUpgradeable.Counter)`

Returns the counter tracker for all the loan IDs in the protocol

#### Return Values

| Type                          | Description                                   |
| ----------------------------- | --------------------------------------------- |
| `CountersUpgradeable.Counter` | the number that will be used in the next loan |

### getUserNftCollateralAmount

`function getUserNftCollateralAmount(address user, address nftAsset) external view returns (uint256)`

Returns the collateral amount for a given user and a specific NFT collection.

#### Call Params

| Name     | Type    | Description                                                    |
| -------- | ------- | -------------------------------------------------------------- |
| user     | address | the address of the user we want to chech the collateral amount |
| nftAsset | address | the address of the underlying asset                            |

#### Return Values

| Type    | Description                                                     |
| ------- | --------------------------------------------------------------- |
| uint256 | the amount the user has as collateral for a specific collection |

### getNftCollateralAmount

`function getNftCollateralAmount(address nftAsset) external view returns (uint256)`

Returns the collateral amount for a specific collection.

#### Call Params

| Name     | Type    | Description                                     |
| -------- | ------- | ----------------------------------------------- |
| nftAsset | address | the address of the underlying asset, collection |

#### Return Values

| Type    | Description                                     |
| ------- | ----------------------------------------------- |
| uint256 | the collateral amount for a specific collection |

### getLoanHighestBid

`function getLoanHighestBid(uint256 loanId) external view returns (address, uint256)`

Returns the address and the bid price of the highest bid during an auction.

#### Call Params

| Name   | Type    | Description        |
| ------ | ------- | ------------------ |
| loanId | uint256 | the id of the loan |

#### Return Values

| Type    | Description        |
| ------- | ------------------ |
| address | the bidder address |
| uint256 | the bid price      |

### getLoanReserveBorrowScaledAmount

`function getLoanReserveBorrowScaledAmount(uint256 loanId) external view returns (address, uint256)`

Returns the scaled amount and the reserve asset for a specific loan.

#### Call Params

| Name    | Type   | Description                                                 |
| ------- | ------ | ----------------------------------------------------------- |
| uint256 | loanId | the loan id to retrive the scalled amount and reserve asset |

#### Return Values

| Type    | Description               |
| ------- | ------------------------- |
| address | the reserve asset (ERC20) |
| uint256 | the scaled amount         |

### getLoanReserveBorrowAmount

`function getLoanReserveBorrowAmount(uint256 loanId) external view returns (address, uint256)`

Returns the amount borrowed and the reserve address for a specific loan.

#### Call Params

| Name   | Type    | Description                     |
| ------ | ------- | ------------------------------- |
| loanId | uint256 | the loan id to retrive the data |

#### Return Values

| Type    | Description         |
| ------- | ------------------- |
| address | the reserve address |
| uint256 | the amount borrowed |

### getLoanCollateralAndReserve

`function getLoanCollateralAndReserve(uint256 loanId) external view returns (address nftAsset, uint256 nftTokenId, address reserveAsset, uint256 scaledAmount)`

Returns the NFT address, tokenId, reserve address and scaled amount for a specific loan.&#x20;

#### Call Params

| Name   | Type    | Description                                 |
| ------ | ------- | ------------------------------------------- |
| loanId | uint256 | the id of the loan we want  to retrive data |

#### Return Values

| Name         | Type    | Description                                   |
| ------------ | ------- | --------------------------------------------- |
| nftAsset     | address | the address of the underlying asset (ERC721)  |
| nftTokenId   | uint256 | the token id of the underlying asset (ERC721) |
| reserveAsset | address | the address of the reserve asset (ERC20)      |
| scaledAmount | uint256 | the scaled amount                             |

### getLoan

`function getLoan(uint256 loanId) external view returns (struct DataTypes.LoanData loanData)`

Returns the struct containing all the info regarding a specific loan.

#### Call Params

| Name   | Type    | Description                      |
| ------ | ------- | -------------------------------- |
| loanId | uint256 | the loan id to retrive data from |

#### Return Values

| Name     | Type               | Description                                                                                                                                                                                                                                  |
| -------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| loanData | DataTypes.LoanData | <p>LoanData struct:<br>loanId, </p><p>state,</p><p>borrower, </p><p>nftAsset, </p><p>nftTokenId, </p><p>reserveAsset, </p><p>scaledAmount,  bidStartTimestamp, bidderAddress,</p><p>bidPrice,</p><p>bidBorrowAmount, firstBidderAddress;</p> |

## Write Methods

### createLoan

`function createLoan(address initiator, address onBehalfOf, address nftAsset, uint256 nftTokenId, address uNftAddress, address reserveAsset, uint256 amount, uint256 borrowIndex) external returns (uint256)`

Create and store the loan, and mint the uNFT to the user as proof of deposit.

#### Call Params

| Name         | Type    | Description                                   |
| ------------ | ------- | --------------------------------------------- |
| initiator    | address | The address of the user initiating the borrow |
| onBehalfOf   | address | The address receiving the loan                |
| nftAsset     | address | The address of the underlying NFT asset       |
| nftTokenId   | uint256 | The token Id of the underlying NFT asset      |
| uNftAddress  | address | The address of the uNFT token                 |
| reserveAsset | address | The address of the underlying reserve asset   |
| amount       | uint256 | The loan amount                               |
| borrowIndex  | uint256 | The index to get the scaled loan amount       |

#### Return Values

| Type    | Description |
| ------- | ----------- |
| uint256 | the loan id |

### updateLoan

`function updateLoan(address initiator, uint256 loanId, uint256 amountAdded, uint256 amountTaken, uint256 borrowIndex) external`

It updates an existing loan.

{% hint style="info" %}
The caller must be a holder of the loan.

The loan must be in an active state
{% endhint %}

#### Call Params

| Name        | Type    | Description                               |
| ----------- | ------- | ----------------------------------------- |
| initiator   | address | The address of the user updating the loan |
| loanId      | uint256 | The loan ID                               |
| amountAdded | uint256 | The amount added to the loan              |
| amountTaken | uint256 | The amount taken from the loan            |
| borrowIndex | uint256 | The index to get the scaled loan amount   |

### repayLoan

`function repayLoan(address initiator, uint256 loanId, address uNftAddress, uint256 amount, uint256 borrowIndex) external`

It will repay the given loan, partially or in whole.

{% hint style="info" %}
The caller must be a holder of the loan.

The caller must send in principal + interest.

The loan must be in an active state.
{% endhint %}

#### Call Params

| Name        | Type    | Description                                  |
| ----------- | ------- | -------------------------------------------- |
| initiator   | address | The address of the user initiating the repay |
| loanId      | uint256 | The loan getting burned                      |
| uNftAddress | address | The address of uNFT                          |
| amount      | uint256 | The amount repaid                            |
| borrowIndex | uint256 | The index to get the scaled loan amount      |

### auctionLoan

`function auctionLoan(address initiator, uint256 loanId, address onBehalfOf, uint256 bidPrice, uint256 borrowAmount, uint256 borrowIndex) external`

It will start and run an auction at a given loan.

{% hint style="info" %}
The price must be greater than the current highest price.

The loan must be in an active or auction state.
{% endhint %}

#### Call Params

| Name         | Type    | Description                                    |
| ------------ | ------- | ---------------------------------------------- |
| initiator    | address | The address of the user initiating the auction |
| loanId       | uint256 | The loan getting auctioned                     |
| onBehalfOf   | address | The user address regarding the auction         |
| bidPrice     | uint256 | The bid price of this auction                  |
| borrowAmount | uint256 | The amount that was borrowed                   |
| borrowIndex  | uint256 | the borrow index                               |

### redeemLoan

`function redeemLoan(address initiator, uint256 loanId, uint256 amountTaken, uint256 borrowIndex) external`

If the loan is in an auction state, and the owner wants to pay it back, making the health factor go above 1.

{% hint style="info" %}
The caller must be a holder of the loan.

The loan must be in an auction state.
{% endhint %}

{% hint style="danger" %}
redeemLoan = auction state.

repayLoan = active state.
{% endhint %}

#### Call Params

| Name        | Type    | Description                                   |
| ----------- | ------- | --------------------------------------------- |
| initiator   | address | The address of the user initiating the borrow |
| loanId      | uint256 | The loan getting redeemed                     |
| amountTaken | uint256 | The taken amount                              |
| borrowIndex | uint256 | The index to get the scaled loan amount       |

### liquidateLoan

`function liquidateLoan(address initiator, uint256 loanId, address uNftAddress, uint256 borrowAmount, uint256 borrowIndex) external`

Liquidate the given loan, sending the NFT to its new owner.

{% hint style="info" %}
The caller must send in principal + interest.

The loan must be in an active state.
{% endhint %}

#### Call Params

| Name         | Type    | Description                                    |
| ------------ | ------- | ---------------------------------------------- |
| initiator    | address | The address of the user initiating the auction |
| loanId       | uint256 | The loan getting burned                        |
| uNftAddress  | address | The address of uNFT                            |
| borrowAmount | uint256 | The borrow amount                              |
| borrowIndex  | uint256 | The index to get the scaled loan amount        |

### buyoutLoan

`function buyoutLoan(address initiator, uint256 loanId, address uNftAddress, uint256 borrowAmount, uint256 borrowIndex, uint256 buyoutAmount) external override onlyLendPool`

Will clear the borrower's debt, pay the protocol and send the NFT to the new owner.

#### Call Params

| Name         | Type    | Description                               |
| ------------ | ------- | ----------------------------------------- |
| initiator    | adress  | The buyers address                        |
| loanId       | uint256 | the Id that will be bought                |
| uNftAddress  | address | the address of the uNFT (the NFT reserve) |
| borrowAmount | uint256 | the debt amount                           |
| borrowIndex  | uint256 | the borrow index                          |
| buyoutAmount | uint256 | the amount to buy the NFT                 |

### liquidateLoanMarket

`function liquidateLoanMarket(uint256 loanId, address uNftAddress, uint256 borrowAmount, uint256 borrowIndex) external override onlyMarketAdapter`

It will liquidate the NFTs in case of no bids or not enough amount in bids  (compared to the markets using the reservoir adapter) when an auction is created.

#### Call Params

| Name         | Type    | Description                                       |
| ------------ | ------- | ------------------------------------------------- |
| loanId       | uint256 | the id of the loan                                |
| uNftAddress  | address | the uNFT address, the address for the NFT reserve |
| borrowAmount | uint256 | the amount borrowed by the user                   |
| borrowIndex  | uint256 | the borrow index                                  |


# Lendpool Address Provider

LendPoolAddressProvider.sol

An Immutable contract address that stores the addresses of the main contracts in the protocol.

{% hint style="info" %}
If you are searching for a smart contract address, we recommend fetching it from the LendPoolAddressProvider.&#x20;
{% endhint %}

The source can be found on [GitHub](https://github.com/UnlockdFinance/unlockd-protocol-v1/blob/master/contracts/protocol/LendPoolAddressesProvider.sol).

## View Methods

### getMarketId

`function getMarketId() external view override returns (string memory)`

Returns the id of the associated Unlockd Market.

#### Return Values

| Type     | Description                              |
| -------- | ---------------------------------------- |
| `string` | a string representation of the market id |

### getAddress

`function getAddress(bytes32 id) public view override returns (address)`

Returns the latest deployed address of a protocol smart contract stored at a given id.&#x20;

#### Call Params

| Name | Type    | Description                                         |
| ---- | ------- | --------------------------------------------------- |
| `id` | bytes32 | id. Example, the Protocol Data Provider uses id 0x1 |

#### Return Values

| Type    | Description                                             |
| ------- | ------------------------------------------------------- |
| address | The address associated with the given bytes32 variable. |

```
// Get the address of the NFTX vault factory
import { utils } from '@ethers/lib/utils';

const id =  utils.keccak256(utils.toUtf8Bytes("NFTX_VAULT_FACTORY"));
const address = poolAddressProvider.getAddress(id);
```

### getLendPool

`function getLendPool() external view override returns (address)`

Returns the proxy address of the lendpool deployed.

#### Return Values

| Type    | Description                            |
| ------- | -------------------------------------- |
| address | The address of the associated LendPool |

### getLendPoolConfigurator

`function getLendPoolConfigurator() external view override returns (address)`

Returns the proxy address of the LendPoolConfigurator deployed.&#x20;

#### Return Values

| Type    | Description                                        |
| ------- | -------------------------------------------------- |
| address | The address of the associated LendPoolConfigurator |

### getPoolAdmin

`function getPoolAdmin() external view override returns (address)`

Returns the address of the LendPool Admin (wallet or contract).

#### Return Values

| Type    | Description                                  |
| ------- | -------------------------------------------- |
| address | The address of the associated LendPool Admin |

### getEmergencyAdmin

`function getEmergencyAdmin() external view override returns (address)`

Returns the address of the Emergency LendPool Admin (wallet or contract).

#### Return Values

| Type    | Description                                            |
| ------- | ------------------------------------------------------ |
| address | The address of the associated Emergency LendPool Admin |

### `getReserveOracle`

`function getReserveOracle() external view override returns (address)`

Returns the proxy address of the ReserveOracle (Will be used for reserves ERC20).

#### Return Values

| Type    | Description                                  |
| ------- | -------------------------------------------- |
| address | The address of the associated Reserve Oracle |

### getNFTOracle

`function getNFTOracle() external view override returns (address)`

Returns the proxy address of the NFTOracle (Will be used for collateral ERC721)

#### Return Values

| Type    | Description                              |
| ------- | ---------------------------------------- |
| address | The address of the associated NFT Oracle |

### getLendPoolLoan

`function getLendPoolLoan() external view override returns (address)`

Returns the proxy address of the LendPoolLoan (Contract associated with the collaterals - loans).

#### Return Values

| Type    | Description                                |
| ------- | ------------------------------------------ |
| address | The address of the associated LendPoolLoan |

### getUNFTRegistry

`function getUNFTRegistry() external view override returns (address)`

Returns the proxy address of the UNFTRegistry.

#### Return Values

| Type    | Description                                |
| ------- | ------------------------------------------ |
| address | The address of the associated UNFTRegistry |

### getIncentivesController

`function getIncentivesController() external view override returns (address)`

Returns the latest deployed address of the IncentivesController.

#### Return Values

| Type    | Description                                          |
| ------- | ---------------------------------------------------- |
| address | The address of the associated Incentives Controller. |

### getUIDataProvider

`function getUIDataProvider() external view override returns (address)`

Returns the proxy address of the UIDataProvider.

#### Return Values

| Type    | Description                                   |
| ------- | --------------------------------------------- |
| address | The address of the associated UIDataProvider. |

### getUnlockdDataProvider

`function getUnlockdDataProvider() external view override returns (address)`

Returns the proxy address of the UnlockdDataProvider.

#### Return Values

| Type    | Description                                        |
| ------- | -------------------------------------------------- |
| address | The address of the associated UnlockdDataProvider. |

### getWalletBalanceProvider

`function getWalletBalanceProvider() external view override returns (address)`

Returns the latest deployed address of the WalletBalanceProvider.

#### Return Values

| Type    | Description                                          |
| ------- | ---------------------------------------------------- |
| address | The address of the associated WalletBalanceProvider. |

### getImplementation

`function getImplementation(address proxyAddress) external view onlyOwner returns (address)`

Returns the latest deployed Implementation address for the given proxy address.

#### Call Params

| Name         | Type    | Description                                                           |
| ------------ | ------- | --------------------------------------------------------------------- |
| proxyAddress | address | the proxy address will return the associated implementation contract. |

#### Return Values

| Type    | Description                                                 |
| ------- | ----------------------------------------------------------- |
| address | The implementation address of the associated proxy Address. |

## Write Methods

### setMarketId

`function setMarketId(string memory marketId) external override onlyOwner`

Set/update the id (Identifier) of the Unlockd market.

#### Call Params

| Name     | Type   | Description              |
| -------- | ------ | ------------------------ |
| marketId | string | the new id of the market |

### setAddressAsProxy

`function setAddressAsProxy(bytes32 id, address implementationAddress, bytes memory encodedDataCall) external override onlyOwner`

Set/update the implementation address of a specified proxied protocol contract

#### Call Params

| Name                  | Type    | Description                                                             |
| --------------------- | ------- | ----------------------------------------------------------------------- |
| id                    | bytes32 | the id of Proxy contract                                                |
| implementationAddress | address | the address of the new implementation contract for the specified proxy. |
| encodedDataCall       | bytes   | \[]                                                                     |

### setAddress

`function setAddress(bytes32 id, address newAddress) external override onlyOwner`

Sets the address of a protocol contract stored at a given id.

#### Call Params

| Name       | Type    | Description                                              |
| ---------- | ------- | -------------------------------------------------------- |
| id         | bytes32 | keccak256 hash of UTF8Bytes string representing Contract |
| newAddress | address | The new address to be set corresponding to the id        |

### setLendPoolImpl

`function setLendPoolImpl(address pool, bytes memory encodedCallData) external override onlyOwner`

Sets/Update the implementation address of the LendPool proxy contract.

#### Call Params

| Name            | Type    | Description                             |
| --------------- | ------- | --------------------------------------- |
| pool            | address | the new lendpool implementation address |
| encodedCallData | bytes   | \[]                                     |

### setLendPoolConfiguratorImpl

`function setLendPoolConfiguratorImpl(address configurator, bytes memory encodedCallData) external override onlyOwner`

Sets/updates the implementation address of the LendPoolConfigurator proxy contract.

#### Call Params

| Name            | Type    | Description                                         |
| --------------- | ------- | --------------------------------------------------- |
| configurator    | address | the new lendPoolConfigurator implementation address |
| encodedCallData | bytes   | \[]                                                 |

### setPoolAdmin

`function setPoolAdmin(address admin) external override onlyOwner`

Sets/updates the LendPoolAdmin wallet or contract address.

#### Call Params

| Name  | Type    | Description                                      |
| ----- | ------- | ------------------------------------------------ |
| admin | address | the new LendPoolAdmin wallet or contract address |

### setEmergencyAdmin

`function setEmergencyAdmin(address emergencyAdmin) external override onlyOwner`

Sets/updates the EmergencyAdmin wallet or contract address.

#### Call Params

| Name           | Type    | Description                                       |
| -------------- | ------- | ------------------------------------------------- |
| emergencyAdmin | address | the new EmergencyAdmin wallet or contract address |

### setReserveOracle

`function setReserveOracle(address reserveOracle) external override onlyOwner`

Sets/updates the ReserveOracle implementation address.

#### Call Params

| Name          | Type    | Description                                   |
| ------------- | ------- | --------------------------------------------- |
| reserveOracle | address | the new Reserve Oracle implementation address |

### setNFTOracle

`function setNFTOracle(address nftOracle) external override onlyOwner`

Sets/updates the NFTOracle implementation address.

#### Call Params

| Name      | Type    | Description                                |
| --------- | ------- | ------------------------------------------ |
| nftOracle | address | the new NFT Oracle implementation address. |

### setLendPoolLoanImpl

`function setLendPoolLoanImpl(address loanAddress, bytes memory encodedCallData) external override onlyOwner`

Sets/updates the LendPoolLoan implementation address.

#### Call Params

| Name            | Type    | Description                                  |
| --------------- | ------- | -------------------------------------------- |
| loanAddress     | address | the new LendPool Loan implementation address |
| encodedCallData | bytes   | \[]                                          |

### setUNFTRegistry

`function setUNFTRegistry(address factory) external override onlyOwner`

Sets/updates the new unftRegisty contract address.

#### Call Params

| Name    |         |                                       |
| ------- | ------- | ------------------------------------- |
| factory | address | the new UNFT Registy contract address |

### setIncentivesController

`function setIncentivesController(address controller) external override onlyOwner`

Sets/updates the new Incentives Controller wallet or contract address.

#### Call Params

| Name       | Type    | Description                                               |
| ---------- | ------- | --------------------------------------------------------- |
| controller | address | the new Incentives Controller wallet or contract address. |

### setUIDataProvider

`function setUIDataProvider(address provider) external override onlyOwner`

Sets/updates the new UIDataProvider contract address.

#### Call Params

| Name     | Type    | Description                               |
| -------- | ------- | ----------------------------------------- |
| provider | address | the new UI Data Provider contract address |

### setUnlockdDataProvider

`function setUnlockdDataProvider(address provider) external override onlyOwner`

Sets/updates the new Unlockd Data Provider contract address.

#### Call Params

| Name     | Type    | Description                                    |
| -------- | ------- | ---------------------------------------------- |
| provider | address | the new Unlockd Data Provider contract address |

### setWalletBalanceProvider

`function setWalletBalanceProvider(address provider) external override onlyOwner`

Sets/updates the new WalletBalanceProvider wallet or contract address.

#### Call Params

| Name     | Type    | Description                                                 |
| -------- | ------- | ----------------------------------------------------------- |
| provider | address | the new Wallet Balance Provider wallet or contract address. |


# uTokens

uToken.sol

The uTokens are the implementation of the interest-bearing token for the Unlockd protocol. \
They are the reserves, where all the underlying tokens will be stored.

## View Methods

### balanceOf

`function balanceOf(address user) public view returns (uint256)`

*Calculates the balance of the user: principal balance + interest generated by the principal*

#### *Call Params*

| Name | Type    | Description                          |
| ---- | ------- | ------------------------------------ |
| user | address | The user whose balance is calculated |

#### Return Values

| Type    | Description             |
| ------- | ----------------------- |
| uint256 | The balance of the user |

### scaledBalanceOf

`function scaledBalanceOf(address user) external view returns (uint256)`

Returns the scaled balance of the user. The scaled balance is the sum of all the updated stored balances divided by the reserve's liquidity index at the moment of the update.

#### Call Params

| Name | Type    | Description                          |
| ---- | ------- | ------------------------------------ |
| user | address | The user whose balance is calculated |

#### Return Values

| Type    | Description                    |
| ------- | ------------------------------ |
| uint256 | The scaled balance of the user |

### getScaledUserBalanceAndSupply

`function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256)`

Returns the scaled balance of the user and the scaled total supply.

#### Call Params

| Name | Type    | Description             |
| ---- | ------- | ----------------------- |
| user | address | The address of the user |

#### Return Values

| Type    | Description                                    |
| ------- | ---------------------------------------------- |
| uint256 | The scaled balance of the user                 |
| uint256 | The scaled balance and the scaled total supply |

### UNDERLYING\_ASSET\_ADDRESS

`function UNDERLYING_ASSET_ADDRESS() public view returns (address)`

Returns the address of the underlying asset of this uToken.

#### Return Values

| Type    | Description                           |
| ------- | ------------------------------------- |
| address | the underlying address of this uToken |

### RESERVE\_TREASURY\_ADDRESS

`function RESERVE_TREASURY_ADDRESS() public view returns (address)`

Returns the address of the Unlockd treasury, receiving the fees on this uToken

#### Return Values

| Type    | Description                                   |
| ------- | --------------------------------------------- |
| address | the addres of the treasury wallet or contract |

### scaledTotalSupply

`function scaledTotalSupply() public view virtual returns (uint256)`

Returns the scaled total supply of the variable debt token. Represents sum(debt/index).

#### Return Values

| Type    | Description             |
| ------- | ----------------------- |
| uint256 | the scaled total supply |

### totalSupply

`function totalSupply() public view returns (uint256)`

Calculates the total supply of the specific uToken since the balance of every single user increases over time. The total supply does that too.

#### Return Values

| Type    | Description              |
| ------- | ------------------------ |
| uint256 | the current total supply |

## Write Methods

### burn

`function burn(address user, address receiverOfUnderlying, uint256 amount, uint256 index) external`

Burns uTokens from `user` and sends the equivalent amount of underlying to receiverOfUnderlying. This happens after a withdrawal.

{% hint style="info" %}
Only callable by the LendPool
{% endhint %}

#### Call Params

| Name                 | Type    | Description                                   |
| -------------------- | ------- | --------------------------------------------- |
| user                 | address | The owner of the uTokens, getting them burned |
| receiverOfUnderlying | address | The address that will receive the underlying  |
| amount               | uint256 | The amount being burned                       |
| index                | uint256 | The new liquidity index of the reserve        |

### mint

`function mint(address user, uint256 amount, uint256 index) external returns (bool)`

Mints `amount` uTokens to the user. This happens after a deposit.

{% hint style="info" %}
Only callable by the LendPool.
{% endhint %}

#### Call Params

| Name   | Type    | Description                             |
| ------ | ------- | --------------------------------------- |
| user   | address | The address receiving the minted tokens |
| amount | uint256 | The amount of tokens getting minted     |
| index  | uint256 | The new liquidity index of the reserve  |

#### Return Values

| Type | Description                                          |
| ---- | ---------------------------------------------------- |
| bool | `true` if the the previous balance of the user was 0 |

### mintToTreasury

`function mintToTreasury(uint256 amount, uint256 index) external`

Mints uTokens to the treasury wallet or contract address.

{% hint style="info" %}
Only callable by the LendPool
{% endhint %}

#### Call Params

| Name   | Type    | Description                            |
| ------ | ------- | -------------------------------------- |
| amount | uint256 | The amount of tokens getting minted    |
| index  | uint256 | The new liquidity index of the reserve |

### transferUnderlyingTo

`function transferUnderlyingTo(address target, uint256 amount) external returns (uint256)`

Transfers the underlying asset to `target`. Used by the LendPool to transfer assets in borrow(), withdraw() and flashLoan()

#### Call Params

| Name   | Type    | Description                    |
| ------ | ------- | ------------------------------ |
| target | address | The recipient of the uTokens   |
| amount | uint256 | The amount getting transferred |

#### Return Values

| Type    | Description            |
| ------- | ---------------------- |
| uint256 | The amount transferred |


# debtTokens

DebtToken.sol

Implements a debt token to track the borrowing positions of users.

## View Methods

### balanceOf

`function balanceOf(address user) public view virtual returns (uint256)`

Calculates the accumulated debt balance of the user.

#### Call Params

| Name | Type    | Description                                    |
| ---- | ------- | ---------------------------------------------- |
| user | address | the users address we want to query the balance |

#### Return Values

| Type    | Description                  |
| ------- | ---------------------------- |
| uint256 | The debt balance of the user |

### scaledBalanceOf

`function scaledBalanceOf(address user) public view virtual returns (uint256)`

Returns the principal debt balance of the user.

#### Call Params

| Name | Type    | Description                                      |
| ---- | ------- | ------------------------------------------------ |
| user | address | the scalled debt amount of the specified address |

#### Return Values

| Type    | Description                                                  |
| ------- | ------------------------------------------------------------ |
| uint256 | The debt balance of the user since the last burn/mint action |

### totalSupply

`function totalSupply() public view virtual returns (uint256)`

Returns the total supply of the variable debt token. Represents the total debt accrued by the users

#### Return Values

| Type    | Description      |
| ------- | ---------------- |
| uint256 | The total supply |

### scaledTotalSupply

`function scaledTotalSupply() public view virtual returns (uint256)`

Returns the scaled total supply of the variable debt token. Represents sum(debt/index).

#### Return Values

| Type    | Description             |
| ------- | ----------------------- |
| uint256 | the scaled total supply |

### getScaledUserBalanceAndSupply

`function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256)`

Returns the principal balance of the user and principal total supply.

#### Parameters

| Name | Type    | Description             |
| ---- | ------- | ----------------------- |
| user | address | The address of the user |

#### Return Values

| Type    | Description                       |
| ------- | --------------------------------- |
| uint256 | The principal balance of the user |
| uint256 | The principal total supply        |

### UNDERLYING\_ASSET\_ADDRESS

`function UNDERLYING_ASSET_ADDRESS() public view returns (address)`

Returns the address of the underlying asset of this uToken.

Return Values

| Type    | Description                              |
| ------- | ---------------------------------------- |
| address | the address of the the underlying asset. |

## Write Methods

`function mint(address initiator, address onBehalfOf, uint256 amount, uint256 index) external returns (bool)`

Mints debt tokens when the user borrows, representing the user's debt.

#### Call Params

| Name       | Type    | Description                                              |
| ---------- | ------- | -------------------------------------------------------- |
| initiator  | address | The address calling borrow                               |
| onBehalfOf | address | The address of the user that will receive the debtTokens |
| amount     | uint256 | The amount of debt being minted                          |
| index      | uint256 | The variable debt index of the reserve                   |

#### Return Values

| Type | Description                                         |
| ---- | --------------------------------------------------- |
| bool | `true` if the the previous balance of the user is 0 |

### burn

`function burn(address user, uint256 amount, uint256 index) external`

It will burn the user's variable debt after redeeming, repaying or getting liquidated.

#### Call Params

| Name   | Type    | Description                            |
| ------ | ------- | -------------------------------------- |
| user   | address | The user whose debt is getting burned  |
| amount | uint256 | The amount getting burned              |
| index  | uint256 | The variable debt index of the reserve |

### transfer

`function transfer(address recipient, uint256 amount) public virtual returns (bool)`

{% hint style="danger" %}
This method is not supported. It will revert the transaction.
{% endhint %}

### allowance

`function allowance(address owner, address spender) public view virtual returns (uint256)`

{% hint style="danger" %}
This method is not supported. It will revert the transaction.
{% endhint %}

### approve

`function approve(address spender, uint256 amount) public virtual returns (bool)`

{% hint style="danger" %}
This method is not supported. It will revert the transaction.
{% endhint %}

### transferFrom

`function transferFrom(address sender, address recipient, uint256 amount) public virtual returns (bool)`

{% hint style="danger" %}
This method is not supported. It will revert the transaction.
{% endhint %}

### increaseAllowance

`function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool)`

{% hint style="danger" %}
This method is not supported. It will revert the transaction.
{% endhint %}

### decreaseAllowance

`function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool)`

{% hint style="danger" %}
This method is not supported. It will revert the transaction.
{% endhint %}

### approveDelegation

`function approveDelegation(address delegatee, uint256 amount) external`

Delegates borrowing power to a user on the specific debt token.

#### Call Params

| Name      | Type    | Description                                                                                                                                                              |
| --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| delegatee | address | the address receiving the delegated borrowing power                                                                                                                      |
| amount    | uint256 | the maximum amount being delegated. Delegation will still respect the liquidation constraints (even if delegated, a delegatee cannot force a delegator HF to go below 1) |

### borrowAllowance

`function borrowAllowance(address fromUser, address toUser) external view returns (uint256)`

returns the borrow allowance of the user

#### Parameters

| Name     | Type    | Description                   |
| -------- | ------- | ----------------------------- |
| fromUser | address | The user to giving allowance  |
| toUser   | address | The user to give allowance to |

#### Return Values

| Type    | Description                     |
| ------- | ------------------------------- |
| uint256 | the current allowance of toUser |


# uNFTs

UNFT.sol

The uNFTs are the collateral receipt and the proof of borrow.\
The NFTs will be stored in this contract.

## View Methods

`function tokenURI(uint256 tokenId) public view virtual returns (string)`

Will return the tokenURI, for a specific tokenId. This is a copy of the real NFT.

#### Call Params

| Name    | Type    | Description |
| ------- | ------- | ----------- |
| tokenId | uint256 | Nft Id      |

#### Return Values

| Type   | Description    |
| ------ | -------------- |
| string | Uri of the NFT |

### minterOf

`function minterOf(uint256 tokenId) external view returns (address)`

Returns the owner of the tokenId token.

#### Call Params

| Name    | Type    | Description                                        |
| ------- | ------- | -------------------------------------------------- |
| tokenId | uint256 | the tokenId that we want to know hows the ower of. |

#### Return Values

| Type    | Description              |
| ------- | ------------------------ |
| address | the address of the owner |

## Write Methods

### mint

`function mint(address to, uint256 tokenId) external`

Mints the uNFT token to the user that added his allowed NFT as collateral.

{% hint style="info" %}
the minted NFT will be a copy, a wrapped version of the real NFT.
{% endhint %}

#### Call Params

| Name    | Type    | Description                               |
| ------- | ------- | ----------------------------------------- |
| to      | address | The owner address receive the uNFT token; |
| tokenId | uint256 | token id of the underlying asset of NFT   |

### burn

`function burn(uint256 tokenId) external`

Will burn the uNFT held by the user. This will happen when the user repays or is liquidated.

#### Call Params

| Name    | Type    | Description                             |
| ------- | ------- | --------------------------------------- |
| tokenId | uint256 | token id of the underlying asset of NFT |

### approve

```
function approve(address to, uint256 tokenId) public virtual
```

{% hint style="danger" %}
This method is not supported. It will revert the transaction
{% endhint %}

### setApprovalForAll

```
function setApprovalForAll(address operator, bool approved) public virtual
```

{% hint style="danger" %}
This method is not supported. It will revert the transaction
{% endhint %}

### safeTransferFrom

```
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual
```

{% hint style="danger" %}
This method is not supported. It will revert the transaction
{% endhint %}

### safeTransferFrom

```
function safeTransferFrom(address from, address to, uint256 tokenId, bytes _data) public virtual
```

{% hint style="danger" %}
This method is not supported. It will revert the transaction
{% endhint %}

### flashLoan

```
function flashLoan(address receiverAddress, uint256[] nftTokenIds, bytes params) external
```


# Reserve Oracle

The Reserve Oracle contract accounts price data for the reserves in the Unlockd protocol and  manages price sources. The protocol’s LendPool contract uses it as a source of truth for reserves prices, which are updated by Chainlink Price Feeds and Aggregators. Aggregators are added to the Oracle and tracked by a mapping, which maps each unique key  (`_priceFeedKeys)` to a single aggregator address. Each aggregator then provides price data for a specific reserve.

The source code of the proxy reserve price provider can be found on [Github](https://github.com/UnlockdFinance/unlockd-protocol-v1/blob/development/contracts/protocol/ReserveOracle.sol).

{% hint style="warning" %}
Always get the latest reserve price oracle address by calling `getReserveOracle()` on the `LendPoolAddressesProvider` contract.
{% endhint %}

## View methods

### getAssetPrice

`function getAssetPrice(address _priceFeedKey) external view override returns (uint256)`

Returns the price for a specific reserve

#### Call Params

| Name            | Type    | Description                                                         |
| --------------- | ------- | ------------------------------------------------------------------- |
| `_priceFeedKey` | address | Unique key of the chainlink aggregator to fetch the price data from |

#### Return values

<table><thead><tr><th width="247.33333333333331">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The reserve price in ETH (WEI format, 18 decimals)</td></tr></tbody></table>

### getAggregator

`function getAggregator(address _priceFeedKey) public view returns (AggregatorV3Interface)`

Returns the aggregator address for a given price feed key

#### Call Params

| Name            | Type    | Description                                                         |
| --------------- | ------- | ------------------------------------------------------------------- |
| `_priceFeedKey` | address | Unique key of the chainlink aggregator to fetch the price data from |

#### Return values

| Type                  | Description            |
| --------------------- | ---------------------- |
| AggregatorV3Interface | The aggregator address |

### getLatestTimestamp

`function getLatestTimestamp(address _priceFeedKey) public view returns (uint256)`

Returns the aggregator's latest timestamp

#### Call params

| Name            | Type    | Description                                                         |
| --------------- | ------- | ------------------------------------------------------------------- |
| `_priceFeedKey` | address | Unique key of the chainlink aggregator to fetch the price data from |

#### Return values

| Type    | Description                       |
| ------- | --------------------------------- |
| uint256 | The aggregator's latest timestamp |

### getTwapPrice

`function getTwapPrice(address _priceFeedKey, uint256 _interval) external view override returns (uint256)`

Returns the TWAP price for a reserve, depending on `_interval`

#### Call params

| Name            | Type    | Description                                                         |
| --------------- | ------- | ------------------------------------------------------------------- |
| `_priceFeedKey` | address | Unique key of the chainlink aggregator to fetch the price data from |
| `_interval`     | uint256 | The requested interval to query the TWAP from                       |

#### Return values

| Type    | Description                                             |
| ------- | ------------------------------------------------------- |
| uint256 | The reserve TWAP price in ETH (WEI format, 18 decimals) |

### isExistedKey

`function isExistedKey(address _priceFeedKey) private view returns (bool)`

Checks if the pricefeed key exists in the pricefeeds currently tracked by the oracle.

#### Call params

| Name            | Type    | Description                                                         |
| --------------- | ------- | ------------------------------------------------------------------- |
| `_priceFeedKey` | address | Unique key of the chainlink aggregator to fetch the price data from |

#### Return values

| Type | Description                                                                                        |
| ---- | -------------------------------------------------------------------------------------------------- |
| bool | Boolean representing if the param's pricefeed key exists (`true`) or not (`false`) in the protocol |

### getPriceFeedLength

`function getPriceFeedLength() public view returns (uint256 length)`

Returns the amount of pricefeeds tracked by the oracle.

#### Return values

| Type    | Description                                    |
| ------- | ---------------------------------------------- |
| uint256 | The amount of pricefeeds tracked by the oracle |

## Write methods

### setAggregators

`function setAggregators(address[] calldata _priceFeedKeys, address[] calldata _aggregators) external onlyOwner`

Sets a list of pricefeed aggregators to be tracked by the oracle.

#### Call params

| Name            | Type    | Description                                                            |
| --------------- | ------- | ---------------------------------------------------------------------- |
| \_priceFeedKeys | address | Array of unique keys of the chainlink aggregators to be added          |
| \_aggregators   | address | The addresses of the pricefeed aggregators to be tracked by the oracle |

### addAggregator

`function addAggregator(address _priceFeedKey, address _aggregator) external onlyOwner`

Adds a single  pricefeed aggregator to be tracked by the oracle.

#### Call params

| Name           | Type    | Description                                                         |
| -------------- | ------- | ------------------------------------------------------------------- |
| \_priceFeedKey | address | Unique key of the chainlink aggregator to be added                  |
| \_aggregator   | address | The address of the pricefeed aggregator to be tracked by the oracle |

### removeAggregator

`function removeAggregator(address _priceFeedKey) external onlyOwner`

Removes a single pricefeed aggregator  from the tracked pricefeeds currently tracked by the oracle.

#### Call params

| Name           | Type    | Description                                          |
| -------------- | ------- | ---------------------------------------------------- |
| \_priceFeedKey | address | Unique key of the chainlink aggregator to be removed |

## ABI

<details>

<summary>ReserveOracle ABI</summary>

```json
[
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "currencyKey",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "aggregator",
          "type": "address"
        }
      ],
      "name": "AggregatorAdded",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "currencyKey",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "aggregator",
          "type": "address"
        }
      ],
      "name": "AggregatorRemoved",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "previousOwner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "OwnershipTransferred",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_priceFeedKey",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_aggregator",
          "type": "address"
        }
      ],
      "name": "addAggregator",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_priceFeedKey",
          "type": "address"
        }
      ],
      "name": "getAggregator",
      "outputs": [
        {
          "internalType": "contract AggregatorV3Interface",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_priceFeedKey",
          "type": "address"
        }
      ],
      "name": "getAssetPrice",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_priceFeedKey",
          "type": "address"
        }
      ],
      "name": "getLatestTimestamp",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getPriceFeedLength",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "length",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_priceFeedKey",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_interval",
          "type": "uint256"
        }
      ],
      "name": "getTwapPrice",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_weth",
          "type": "address"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "priceFeedKeys",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "priceFeedMap",
      "outputs": [
        {
          "internalType": "contract AggregatorV3Interface",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_priceFeedKey",
          "type": "address"
        }
      ],
      "name": "removeAggregator",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "renounceOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "_priceFeedKeys",
          "type": "address[]"
        },
        {
          "internalType": "address[]",
          "name": "_aggregators",
          "type": "address[]"
        }
      ],
      "name": "setAggregators",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "transferOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "weth",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ]
```

</details>


# NFT Oracle

The NFT Oracle contract accounts price data for the NFTs held in the Unlockd protocol. The protocol’s LendPool contract uses it as a source of truth for NFT prices, which are updated externally by the Unlockd team. We leverage powerful price appraisers, such as [Upshot](https://upshot.xyz/), [NFTBank](https://nftbank.ai/) and [Ginoa](https://ginoa.io/) in order to provide Unlockd users with the most competitive LTV in the industry.

The source code of the proxy NFT price provider can be found on [Github](https://github.com/UnlockdFinance/unlockd-protocol-v1/blob/development/contracts/protocol/NFTOracle.sol).

{% hint style="warning" %}
Always get the latest NFT price oracle address by calling `getNFTOracle()` on the `LendPoolAddressesProvider` contract.
{% endhint %}

## View methods

### getNFTPrice

`function getNFTPrice(address _collection, uint256 _tokenId) external view override onlyExistingCollection(_collection) returns (uint256)`

Returns the price for a specific NFT

#### Call params

| Name         | Type    | Description                |
| ------------ | ------- | -------------------------- |
| \_collection | address | The NFT collection address |
| \_tokenId    | uint256 | The NFT token Id           |

#### Return values

| Type    | Description                                    |
| ------- | ---------------------------------------------- |
| uint256 | The NFT price in ETH (WEI format, 18 decimals) |

### getMultipleNFTPrices

`function getMultipleNFTPrices(address[] calldata _collections, uint256[] calldata _tokenIds) external view override returns (uint256[] memory)`

Returns the price for multiple NFTs.

#### Call params

| Name          | Type    | Description                  |
| ------------- | ------- | ---------------------------- |
| \_collections | address | The NFT collection addresses |
| \_tokenIds    | uint256 | The NFT token Ids            |

#### Return values

| Type       | Description                                              |
| ---------- | -------------------------------------------------------- |
| uint256\[] | The array of NFT prices in ETH (WEI format, 18 decimals) |

### getNFTPriceNFTX

`function getNFTPriceNFTX(address _collection, uint256 _tokenId) external view override onlyExistingCollection(_collection) returns (uint256)`

Returns the spot price for a given NFT in the NFTX market.

#### Call params

| Name         | Type    | Description                |
| ------------ | ------- | -------------------------- |
| \_collection | address | The NFT collection address |
| \_tokenId    | uint256 | The NFT token Id           |

#### Return values

| Type    | Description                       |
| ------- | --------------------------------- |
| uint256 | The spot price in the NFTX market |

## Write methods

### setNFTPrice

`function setNFTPrice( address _collection, uint256 _tokenId, uint256 _price ) external override onlyPriceManager`

Sets the price for a given NFT.

#### Call params

| Name         | Type    | Description                                                  |
| ------------ | ------- | ------------------------------------------------------------ |
| \_collection | address | The NFT collection address                                   |
| \_tokenId    | uint256 | The NFT token Id                                             |
| \_price      | uint256 | The price to set to the NFT in ETH (WEI format, 18 decimals) |

### setMultipleNFTPrices

`function setMultipleNFTPrices( address[] calldata _collections, uint256[] calldata _tokenIds, uint256[] calldata _prices ) external override onlyPriceManager`

Sets the price for multiple NFTs.

#### Call params

| Name          | Type       | Description                                                   |
| ------------- | ---------- | ------------------------------------------------------------- |
| \_collections | address\[] | The NFT collection addresses                                  |
| \_tokenIds    | uint256\[] | The NFT token Ids                                             |
| \_prices      | uint256\[] | The price to set to the NFTs in ETH (WEI format, 18 decimals) |

### addCollection

`function addCollection(address _collection) external onlyOwner`

Adds a collection to the be supported by NFT oracle.

#### Call params

| Name         | Type    | Description                                     |
| ------------ | ------- | ----------------------------------------------- |
| \_collection | address | The NFT collection address to add to the oracle |

### setCollections

`function setCollections(address[] calldata _collections) external onlyOwner`

Adds multiple collections to the be supported by NFT oracle.

#### Call params

| Name          | Type    | Description                                       |
| ------------- | ------- | ------------------------------------------------- |
| \_collections | address | The NFT collection addresses to add to the oracle |

### removeCollection

`function removeCollection(address _collection) external onlyOwner`

Removes a collection that is currently supported by NFT oracle.

#### Call params

| Name          | Type    | Description                                          |
| ------------- | ------- | ---------------------------------------------------- |
| \_collections | address | The NFT collection address to remove from the oracle |

### setPause

`function setPause(address _collection, bool paused) external override onlyOwner onlyExistingCollection(_collection)`

Pauses a specific collection in the NFT oracle.

#### Call params

| Name         | Type    | Description                                                |
| ------------ | ------- | ---------------------------------------------------------- |
| \_collection | address | The NFT collection address to be paused                    |
| paused       | bool    | The pause status (`true` for paused, `false` for unpaused) |

### setPriceManagerStatus

`function setPriceManagerStatus(address newPriceManager, bool val) external onlyOwner`

Adds or removes an address to be allowed to act as the price manager.

{% hint style="warning" %}
The price manager addresses are the only ones allowed to set prices in the Unlockd protocol. Currently, they are addresses managed by the Unlockd team.
{% endhint %}

#### Call params

| Name            | Type    | Description                                                                                                                          |
| --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| newPriceManager | address | The address of the price manager to set the status to                                                                                |
| val             | bool    | The price manger status (`true` to allow the address to act as a price manger, `false` to deny the address to act as a price manger) |


# WETH Gateway

If you need to use native ETH in the protocol, it must first be wrapped into WETH. The WETH Gateway contract is a helper contract to easily wrap and unwrap ETH as necessary when interacting with the protocol, since only ERC20 is used within protocol interactions. This allows users to interact with the LendPool seamlessly without previously wrapping ETH themselves.

The source code of the WETH Gateway can be found on [Github](https://github.com/UnlockdFinance/unlockd-protocol-v1/blob/development/contracts/protocol/WETHGateway.sol).

## View methods

### isCallerInWhitelist

`function isCallerInWhitelist(address caller) external view returns (bool)`

Checks if the caller is whitelisted.

#### Call params

| Name   | Type    | Description               |
| ------ | ------- | ------------------------- |
| caller | address | The address to be checked |

#### Return values

| Type | Description                                                    |
| ---- | -------------------------------------------------------------- |
| bool | Returns `true` if the caller is whitelisted, `false` otherwise |

### getWETHAddress

`function getWETHAddress() external view returns (address)`

Returns the WETH address currently set in the WETH Gateway.

#### Return values

| Type    | Description      |
| ------- | ---------------- |
| address | The WETH address |

## Write methods

### depositETH

`function depositETH(address onBehalfOf, uint16 referralCode) external payable override nonReentrant`

Deposits the user-chosen amount of ETH into the protocol, minting the same amount passed as `msg.value` of corresponding uTokens, and transferring them to the `onBehalfOf` address.

Example: Bob deposits 100 ETH into Unlockd, and gets 100 uWETH in return as proof of the deposited amount.

{% hint style="danger" %}
The referral program is coded but inactive. You can pass a 0 as `referralCode.`
{% endhint %}

{% hint style="warning" %}
Ensure that the `depositETH()` transaction also includes the amount of ETH you are depositing in the `msg.value`.
{% endhint %}

#### Call params

| Name         | Type    | Description                                                                                                               |
| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------- |
| onBehalfOf   | address | <p>address whom will receive the uWETH.<br>Use <code>msg.sender</code> when the uTokens should be sent to the caller.</p> |
| referralCode | uint16  | Referral code. The referral program is currently in development. Therefore, `referralCode` must be set to 0.              |
|              |         |                                                                                                                           |

### withdrawETH

`function withdrawETH(uint256 amount, address to) external override nonReentrant`

Withdraws `amount` of the WETH, unwraps it to ETH, and transfers the ETH to the `to` address.

Example: Bob withdraws 10 ETH. Bob will get 10 ETH and will burn the same amount in uTokens.

{% hint style="warning" %}
Ensure you set the relevant ERC20 allowance of uWETH, before calling this function, so the `WETHGateway` contract can burn the associated uWETH.
{% endhint %}

#### Call params

| Name   | Type    | Description                                 |
| ------ | ------- | ------------------------------------------- |
| amount | uint256 | The amount to be withdrawn                  |
| to     | address | address that will receive the unwrapped ETH |

### borrowETH

`function borrowETH(uint256 amount, address nftAsset, uint256 nftTokenId, address onBehalfOf, uint16 referralCode) external override nonReentrant`

Borrows `amount` of ETH, sending the `amount` of unwrapped WETH to `msg.sender`.

Example: Alice borrows 10 ETH using her Lockey NFT with tokenid 1 as collateral.&#x20;

{% hint style="danger" %}
The referral program is coded but inactive. You can pass a 0 as `referralCode.`
{% endhint %}

{% hint style="warning" %}
The borrowing can only be done if your NFT is configured on the protocol.

To do this, the triggerUserCollateral needs to be called first. \
Also, there's a `_timeFrame` variable configured that will validate the time between configuring the NFT and the borrow. If the time is exceeded, it will revert.<br>

The `_timeFrame` can be checked with the `getTimeframe()` function in the LendPool contract
{% endhint %}

#### Call params

| Amount       | Type    | Description                                                                                                                       |
| ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| amount       | uint256 | Amount to be borrowed, expressed in wei units                                                                                     |
| nftAsset     | address | The NFT contract address                                                                                                          |
| nftTokenId   | uint256 | The NFT token Id                                                                                                                  |
| onBehalfOf   | address | <p>address of user who will incur the debt.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |
| referralCode | uint16  | Referral code. The referral program is currently in development. Therefore, `referralCode` must be set to 0.                      |

### repayETH

`function _repayETH( address nftAsset, uint256 nftTokenId, uint256 amount, uint256 accAmount ) internal returns (uint256, bool)`

Repays a borrowed `amount` equal to or less than the amount owed from the specified collateral, `nftAsset`. It will burn the same `amount` of `debt tokens`.

Example: Alice decides to pay 2 ETH from the borrowed amount. Alice will use her uNFT to identify the loan, will give 2 ETH and will burn the same amount in debt tokens.

{% hint style="warning" %}
Ensure that the `repayETH()` transaction also includes the amount of ETH you are repaying in the `msg.value`.
{% endhint %}

#### Call params

| Name       | Type    | Description                                 |
| ---------- | ------- | ------------------------------------------- |
| nftAsset   | address | The NFT contract address                    |
| nftTokenId | uint256 | The NFT token Id                            |
| amount     | uint256 | Amount to be repaid, expressed in wei units |
| accAmount  | uint256 | The accumulated amount                      |

#### Return values

| Type    | Description                                                        |
| ------- | ------------------------------------------------------------------ |
| uint256 | The paid amount                                                    |
| bool    | `true` if the total amount is repaid or `false` if partially paid. |

### auctionETH

`function auctionETH(address nftAsset, uint256 nftTokenId, address onBehalfOf ) external payable override nonReentrant`

Places a bid for an NFT whose current health factor is below one. The users can trigger an auction if they want to buy the collateral asset, placing a bid for the `msg.value`amount. New bids should always be higher than the loan borrowed amount, and 1% higher than the previous bid (in case there is one). The first user to bid will always receive a 2.5% bid incentive for being the first bidder.

Example: Alice's NFT price went down,  together with her loan's health factor (HF),  which is now below 1. Bob decides to bid for that NFT. \
If there's a second bid, Bob's bid will be cancelled and the new bid will the the current winning bid. Bob will still receive a 2.5% reward fee for being the first bidder. The bidFine will also be paid if Alice decides to redeem part of the debt and make the HF go above one.

{% hint style="warning" %}
Ensure that the `auctionETH()` transaction also includes the amount of ETH you are bidding for in the `msg.value`.
{% endhint %}

#### Call params

| Name       | Type    | Description                                                                                                                          |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| nftAsset   | address | The NFT contract address                                                                                                             |
| nftTokenId | uint256 | The NFT token Id                                                                                                                     |
| onBehalfOf | address | <p>address of user who will incur the auction.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |

### redeemETH

`function redeemETH( address nftAsset, uint256 nftTokenId, uint256 amount, uint256 bidFine ) external payable override nonReentrant returns (uint256)`

Allows a borrower to increase his loan's Health Factor in case it is below 1. In order to redeem, a `bidFine`  should be paid by the borrower to the current loan bidder (in case there is one).

Example: Alice's NFT price went down,  together with her loan's health factor (HF),  which is now below 1. Bob decides to bid for that NFT. \
After Bob's bid, Alice decides to redeem her NFT in order to increase her loan's HF and avoid getting liquidated. Bob will receive his bidding amount back, plus a `bidFine` reward fee for being the first bidder.&#x20;

{% hint style="info" %}
The redeem `amount` needs to be higher than the `(borrowAmount * redeemThreshold)/100`
{% endhint %}

{% hint style="warning" %}
Ensure that the`redeemETH()` transaction also includes the amount of ETH you are redeeming, as well as the bid fine you are transferring in the `msg.value`.
{% endhint %}

#### Call params

| Name       | Type    | Description                                           |
| ---------- | ------- | ----------------------------------------------------- |
| nftAsset   | address | The NFT contract address                              |
| nftTokenId | uint256 | The NFT token Id                                      |
| amount     | uint256 | Amount to be redeemed, expressed in wei units         |
| bidFine    | uint256 | Amount to be paid as bid fine, expressed in wei units |

#### Return values

| Type    | Description                                           |
| ------- | ----------------------------------------------------- |
| uint256 | The total payback (amount redeemed plus the bid fine) |

### liquidateETH

`function liquidateETH(address nftAsset, uint256 nftTokenId) external payable override nonReentrant returns (uint256)`

Allows an auction winner to liquidate the position and get the NFT.

Example: Bob wins the auction. He can call this function to get his collateral (NFT) into his wallet.

{% hint style="info" %}
The `msg.value` amount is the amount to be sent in case the bid price can't cover the borrow amount (for example, if a user takes a long time to redeem and the borrow amount needed to be paid has increased substantially due to interest rates)
{% endhint %}

{% hint style="warning" %}
Ensure that the`redeemETH()` transaction also includes the amount of ETH you want to add as amount to `liquidate` as `msg.value`.
{% endhint %}

#### Call params

| Name       | Type    | Amount                   |
| ---------- | ------- | ------------------------ |
| nftAsset   | address | The NFT contract address |
| nftTokenId | uint256 | The NFT token Id         |

#### Return values

| Type    | Amount                                                                                                  |
| ------- | ------------------------------------------------------------------------------------------------------- |
| uint256 | The extra debt amount (in case there is one) paid due to last bid price can not cover the borrow amount |

### authorizeLendPoolNFT

`function authorizeLendPoolNFT(address[] calldata nftAssets) external nonReentrant onlyOwner`

Approves the LendPool for the given NFT assets

#### Call params

| Name      | Type       | Description             |
| --------- | ---------- | ----------------------- |
| nftAssets | address\[] | The array of NFT assets |

### authorizeCallerWhitelist

`function authorizeCallerWhitelist(address[] calldata callers, bool flag) external nonReentrant onlyOwner`

Authorizes/unauthorizes a list of callers for the whitelist

#### Call params

| Name    | Type       | Description                           |
| ------- | ---------- | ------------------------------------- |
| callers | address\[] | The array of callers to be authorized |
| flag    | bool       | The flag to authorize/unauthorize     |

### buyoutETH

`function buyoutETH(address nftAsset, uint256 nftTokenId, address onBehalfOf) external payable override nonReentrant`

Allows the user to do a buyout on an auction using ETH.

#### Call Params

| Name       | Type    | Description                                                                                                                         |
| ---------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| nftAsset   | address | The NFT contract address                                                                                                            |
| nftTokenId | uint256 | The NFT token Id                                                                                                                    |
| onBehalfOf | address | <p>address of user who will incur the buyout.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |

### buyDebtETH

`function buyDebtETH(address nftAsset, uint256 nftTokenId, address onBehalfOf) external payable nonReentrant loanReserveShouldBeWETH(nftAsset, nftTokenId)`

This will allow the buyer to buy a debt listing directly using ETH.

#### Call Params

| Name       | Type    | Description                                                                                                                          |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| nftAsset   | address | The NFT contract address                                                                                                             |
| nftTokenId | uint256 | The NFT token Id                                                                                                                     |
| onBehalfOf | address | <p>address of user who will incur the buyDebt.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |

### bidDebtETH

`function bidDebtEth(address nftAsset, uint256 nftTokenId, address onBehalfOf) external payable override nonReentrant loanReserveShouldBeWETH(nftAsset, nftTokenId)`

Allows the user to bid on the debt market directly using ETH.

#### Call Params

| Name       | Type    | Description                                                                                                                          |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| nftAsset   | address | The NFT contract address                                                                                                             |
| nftTokenId | uint256 | The NFT token Id                                                                                                                     |
| onBehalfOf | address | <p>address of user who will incur the bidDebt.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |


# Punk Gateway

If you need to use native CryptoPunks in the protocol, they must first be wrapped into WPunks. The Punk Gateway contract is a helper contract to easily wrap and unwrap Punks as necessary when interacting with the protocol, since only ERC721 is used within protocol interactions. This allows users to interact with the LendPool seamlessly without previously wrapping Punks themselves.

The source code of the Punk Gateway can be found on [Github](https://github.com/UnlockdFinance/unlockd-protocol-v1/blob/master/contracts/protocol/PunkGateway.sol).

## View methods

### isCallerInWhitelist

`function isCallerInWhitelist(address caller) external view returns (bool)`

Checks if the caller is whitelisted.

#### Call params

| Name   | Type    | Description               |
| ------ | ------- | ------------------------- |
| caller | address | The address to be checked |

#### Return values

| Type | Description                                                    |
| ---- | -------------------------------------------------------------- |
| bool | Returns `true` if the caller is whitelisted, `false` otherwise |

## Write methods

### borrowETH

`function borrowETH( uint256 amount, uint256 punkIndex, address onBehalfOf, uint16 referralCode ) external override nonReentrant`

Borrows `amount` of ETH, sending the `amount` of unwrapped WETH to `msg.sender` , and setting `punkIndex` punk as collateral.

Example: Alice borrows 10 ETH using her Punk with `punkIndex` 1 as collateral.&#x20;

{% hint style="danger" %}
The referral program is coded but inactive. You can pass a 0 as `referralCode.`
{% endhint %}

{% hint style="warning" %}
The borrowing can only be done if your NFT is configured on the protocol.

To do this, the triggerUserCollateral needs to be called first. \
Also, there's a `_timeFrame` variable configured that will validate the time between configuring the NFT and the borrow. If the time is exceeded, it will revert.

The `_timeFrame` can be checked with the `getTimeframe()` function in the LendPool contract
{% endhint %}

#### Call params

| Amount       | Type    | Description                                                                                                                       |
| ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| amount       | uint256 | Amount to be borrowed, expressed in wei units                                                                                     |
| punkIndex    | uint256 | The punk index                                                                                                                    |
| onBehalfOf   | address | <p>address of user who will incur the debt.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |
| referralCode | uint16  | Referral code. The referral program is currently in development. Therefore, `referralCode` must be set to 0.                      |

###

### borrow

`function borrow( address reserveAsset, uint256 amount, uint256 punkIndex, address onBehalfOf, uint16 referralCode ) external override nonReentrant`

Borrows `amount` of `reserveAsset`, sending it to `msg.sender` , and setting `punkIndex` punk as collateral.

Example: Alice borrows 10 WETH using her Punk with `punkIndex` 1 as collateral.&#x20;

{% hint style="danger" %}
The referral program is coded but inactive. You can pass a 0 as `referralCode.`
{% endhint %}

{% hint style="warning" %}
The borrowing can only be done if your NFT is configured on the protocol.

To do this, the triggerUserCollateral needs to be called first. \
Also, there's a `_timeFrame` variable configured that will validate the time between configuring the NFT and the borrow. If the time is exceeded, it will revert.

The `_timeFrame` can be checked with the `getTimeframe()` function in the LendPool contract
{% endhint %}

#### Call params

| Name         | Type    | Description                                                                                                                       |
| ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| reserveAsset | address | The reserve address to be borrowed                                                                                                |
| amount       | uint256 | Amount to be borrowed, expressed in wei units                                                                                     |
| punkIndex    | uint256 | The punk index                                                                                                                    |
| onBehalfOf   | address | <p>address of user who will incur the debt.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |
| referralCode | uint16  | Referral code. The referral program is currently in development. Therefore, `referralCode` must be set to 0.                      |

### repayETH

`function repayETH(uint256 punkIndex, uint256 amount) external payable override nonReentrant returns (uint256, bool)`

Repays a borrowed `amount` of ETH equal to or less than the amount owed from the specified collateral punk with `punkIndex`. It will burn the same `amount` of `debt tokens`.

Example: Alice decides to pay 2 ETH from her borrowed amount. Alice will use her uNFT to identify the loan, will give 2 ETH and will burn the same amount in debt tokens.

{% hint style="warning" %}
Ensure that the `repayETH()` transaction also includes the amount of ETH you are repaying in the `msg.value`.
{% endhint %}

#### Call params

| Name      | Type    | Description                                 |
| --------- | ------- | ------------------------------------------- |
| punkIndex | uint256 | The punk index                              |
| amount    | uint256 | Amount to be repaid, expressed in wei units |

#### Return values

| Type    | Description                                                          |
| ------- | -------------------------------------------------------------------- |
| uint256 | The repaid amount                                                    |
| bool    | `true` if the total amount is repaid or `false` if partially repaid. |

### repay

`function repay(uint256 punkIndex, uint256 amount) external override nonReentrant returns (uint256, bool)`

Repays a borrowed `amount` equal to or less than the amount owed from the specified collateral punk with `punkIndex`. It will burn the same `amount` of `debt tokens`.

Example: Alice decides to pay 2 WETH from her borrowed amount. Alice will use her uNFT to identify the loan, will give 2 WETH and will burn the same amount in debt tokens.

#### Call params

| Name      | Type    | Description                                 |
| --------- | ------- | ------------------------------------------- |
| punkIndex | uint256 | The punk index                              |
| amount    | uint256 | Amount to be repaid, expressed in wei units |

#### Return values

| Type    | Description                                                          |
| ------- | -------------------------------------------------------------------- |
| uint256 | The repaid amount                                                    |
| bool    | `true` if the total amount is repaid or `false` if partially repaid. |

### auctionETH

`function auctionETH(uint256 punkIndex, address onBehalfOf) external payable override nonReentrant`

Places a bid in ETH for a Punk whose current health factor is below one. The users can trigger an auction if they want to buy the collateral asset, placing a bid for the `msg.value`amount. New bids should always be higher than the loan borrowed amount, and 1% higher than the previous bid (in case there is one). The first user to bid will always receive a 2.5% bid incentive for being the first bidder.

Example: Alice's Punk price went down, together with her loan's health factor (HF), which is now below 1. Bob decides to bid for that Punk. \
If there's a second bid, Bob's bid will be cancelled and the new bid will the the current winning bid. Bob will still receive a 2.5% reward fee for being the first bidder. The bidFine will also be paid if Alice decides to redeem part of the debt and make the HF go above one.

{% hint style="warning" %}
Ensure that the `auctionETH()` transaction also includes the amount of ETH you are bidding for in the `msg.value`.
{% endhint %}

#### Call params

| Name       | Type    | Description                                                                                                                          |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| punkIndex  | uint256 | The punk index                                                                                                                       |
| onBehalfOf | address | <p>address of user who will incur the auction.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |

###

### auction

`function auction( uint256 punkIndex, uint256 bidPrice, address onBehalfOf ) external override nonReentrant`

Places a bid for a Punk whose current health factor is below one. The users can trigger an auction if they want to buy the collateral asset, placing a bid for the `msg.value`amount. New bids should always be higher than the loan borrowed amount, and 1% higher than the previous bid (in case there is one). The first user to bid will always receive a 2.5% bid incentive for being the first bidder.

Example: Alice's Punk price went down, together with her loan's health factor (HF), which is now below 1. Bob decides to bid for that Punk. \
If there's a second bid, Bob's bid will be cancelled and the new bid will the the current winning bid. Bob will still receive a 2.5% reward fee for being the first bidder. The bidFine will also be paid if Alice decides to redeem part of the debt and make the HF go above one.

#### Call params

| Name       | Type    | Description                                                                                                                          |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| punkIndex  | uint256 | The punk index                                                                                                                       |
| bidPrice   | uint256 | The bid price                                                                                                                        |
| onBehalfOf | address | <p>address of user who will incur the auction.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user.</p> |

### redeemETH

`function redeemETH( uint256 punkIndex, uint256 amount, uint256 bidFine ) external payable override nonReentrant returns (uint256)`

Allows a borrower to increase his loan's Health Factor using ETH in case it is below 1. In order to redeem, a `bidFine`  should be paid by the borrower to the current loan bidder (in case there is one).

Example: Alice's Punk price went down,  together with her loan's health factor (HF),  which is now below 1. Bob decides to bid for that Punk. \
After Bob's bid, Alice decides to redeem her Punk in order to increase her loan's HF and avoid getting liquidated. Bob will receive his bidding amount back, plus a `bidFine` reward fee for being the first bidder.&#x20;

{% hint style="info" %}
The redeem `amount` needs to be higher than the `(borrowAmount * redeemThreshold)/100`
{% endhint %}

{% hint style="warning" %}
Ensure that the`redeemETH()` transaction also includes the amount of ETH you are redeeming, as well as the bid fine you are transferring in the `msg.value`.
{% endhint %}

#### Call params

| Name      | Type    | Description                                           |
| --------- | ------- | ----------------------------------------------------- |
| punkIndex | uint256 | The punk index                                        |
| amount    | uint256 | Amount to be redeemed, expressed in wei units         |
| bidFine   | uint256 | Amount to be paid as bid fine, expressed in wei units |

#### Return values

| Type    | Description                                           |
| ------- | ----------------------------------------------------- |
| uint256 | The total payback (amount redeemed plus the bid fine) |

### redeem

`function redeem( uint256 punkIndex, uint256 amount, uint256 bidFine ) external override nonReentrant returns (uint256)`

Allows a borrower to increase his loan's Health Factor in case it is below 1. In order to redeem, a `bidFine`  should be paid by the borrower to the current loan bidder (in case there is one).

Example: Alice's Punk price went down,  together with her loan's health factor (HF),  which is now below 1. Bob decides to bid for that Punk. \
After Bob's bid, Alice decides to redeem her Punk in order to increase her loan's HF and avoid getting liquidated. Bob will receive his bidding amount back, plus a `bidFine` reward fee for being the first bidder.&#x20;

{% hint style="info" %}
The redeem `amount` needs to be higher than the `(borrowAmount * redeemThreshold)/100`
{% endhint %}

#### Call params

| Name      | Type    | Description                                           |
| --------- | ------- | ----------------------------------------------------- |
| punkIndex | uint256 | The punk index                                        |
| amount    | uint256 | Amount to be redeemed, expressed in wei units         |
| bidFine   | uint256 | Amount to be paid as bid fine, expressed in wei units |

#### Return values

| Type    | Description                                           |
| ------- | ----------------------------------------------------- |
| uint256 | The total payback (amount redeemed plus the bid fine) |

### liquidateETH

`function liquidateETH(uint256 punkIndex) external payable override nonReentrant returns (uint256)`

Allows an auction winner to liquidate the position and get the Punk.

Example: Bob wins the auction. He can call this function to get his collateral (Punk) into his wallet.

{% hint style="info" %}
The `msg.value` amount is the amount to be sent in case the bid price can't cover the borrow amount (for example, if a user takes a long time to redeem and the borrow amount needed to be paid has increased substantially due to interest rates)
{% endhint %}

{% hint style="warning" %}
Ensure that the`redeemETH()` transaction also includes the amount of ETH you want to add as amount to `liquidate` as `msg.value`.
{% endhint %}

#### Call params

| Name      | Type    | Description    |
| --------- | ------- | -------------- |
| punkIndex | uint256 | The punk index |

#### Return values

| Type    | Description                                                                                             |
| ------- | ------------------------------------------------------------------------------------------------------- |
| uint256 | The extra debt amount (in case there is one) paid due to last bid price can not cover the borrow amount |

### liquidate

`function liquidate(uint256 punkIndex, uint256 amount) external override nonReentrant returns (uint256)`

Allows an auction winner to liquidate the position and get the Punk.

Example: Bob wins the auction. He can call this function to get his collateral (Punk) into his wallet.

{% hint style="info" %}
The `amount` is the amount to be sent in case the bid price can't cover the borrow amount (for example, if a user takes a long time to redeem and the borrow amount needed to be paid has increased substantially due to interest rates)
{% endhint %}

#### Call params

| Name      | Type    | Description                                                                     |
| --------- | ------- | ------------------------------------------------------------------------------- |
| punkIndex | uint256 | The punk index                                                                  |
| amount    | uint256 | The extra amount to be sent in case the bid price can't cover the borrow amount |

#### Return values

| Type    | Description                                                                                             |
| ------- | ------------------------------------------------------------------------------------------------------- |
| uint256 | The extra debt amount (in case there is one) paid due to last bid price can not cover the borrow amount |

### authorizeLendPoolERC20

`function authorizeLendPoolERC20(address[] calldata tokens) external nonReentrant onlyOwner`

Approves the lendpool for given tokens

#### Call params

| Name   | Type       | Description         |
| ------ | ---------- | ------------------- |
| tokens | address\[] | The array of tokens |

### authorizeCallerWhitelist

`function authorizeCallerWhitelist(address[] calldata callers, bool flag) external nonReentrant onlyOwner`

Authorizes/unauthorizes a list of callers for the whitelist

#### Call params

| Name    | Type       | Description                           |
| ------- | ---------- | ------------------------------------- |
| callers | address\[] | The array of callers to be authorized |
| flag    | bool       | The flag to authorize/unauthorize     |

### buyoutETH

`function buyoutETH(uint256 punkIndex, address onBehalfOf) external payable override nonReentrant`

This will allow the buyers in case of an auction to do a buyout on a crypto punk NFT using ETH.

{% hint style="info" %}
The address onBehalfOf can be the msg.sender or any address given by the user when executing the function.
{% endhint %}

{% hint style="warning" %}
The amount will be passed as msg.value, should be equal to the NFT Price.
{% endhint %}

#### Call Params

| Name       | Type    | Description                                                                                                                        |
| ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| punkIndex  | uint256 | The punk index (tokenId)                                                                                                           |
| onBehalfOf | address | <p>address of user who will incur the buyout.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user</p> |

### buyout

`function buyout(uint256 punkIndex, uint256 amount, address onBehalfOf) external override nonReentrant`

Allows the buyers in case of an auction to do a buyout on a crypto punk NFT using WETH.

#### Call Params

| Name       | Type    | Description                                                                                                                        |
| ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| punkIndex  | uint256 | The punk index (tokenId)                                                                                                           |
| amount     | uint256 | the amount to execute the buyout in WETH                                                                                           |
| onBehalfOf | address | <p>address of user who will incur the buyout.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user</p> |

### buyDebtPunk

`function buyDebtPunkETH(uint256 punkIndex, address onBehalfOf, uint256 amount) external override nonReentrant`

Allows the user to buy a debt market listing for a crypto punk using WETH

| Name       | Type    | Description                                                                                                                               |
| ---------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| punkIndex  | uint256 | The punk index (tokenId)                                                                                                                  |
| onBehalfOf | address | <p>address of user who will incur the buy debt punk.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user</p> |
| amount     | uint256 | the amount to execute the buyout(buy) in WETH                                                                                             |

### buyDebtPunkETH

`function buyDebtPunk(uint256 punkIndex, address onBehalfOf) external override nonReentrant`

Allows the user to buy a debt market listing for a crypto punk using ETH directly

{% hint style="info" %}
The address onBehalfOf can be the msg.sender or any address given by the user when executing the function.
{% endhint %}

{% hint style="warning" %}
The amount will be passed as msg.value, should be equal to the NFT Price.
{% endhint %}

| Name       | Type    | Description                                                                                                                               |
| ---------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| punkIndex  | uint256 | The punk index (tokenId)                                                                                                                  |
| onBehalfOf | address | <p>address of user who will incur the buy debt punk.</p><p>Use <code>msg.sender</code> when not calling on behalf of a different user</p> |


# Debt Market

The Debt Market allows users to sell their debt, also called loans. When a user borrows, he becomes a borrower and starts a loan at Unlockd. If the user wants, he can add it to the marketplace and sell it for a fixed price or to the highest bidder (using an English Auction over an X period of your choice). The borrower will create a listing, asking for an amount for him. If a buyer wins an auction or buys the fixed term, the protocol will send the user the amount he asked for and burn his debt, minting the same debt and giving the uNFT to the new owner. The buyer must remind himself that his buying the debt! To withdraw the NFT, the new owner must also pay the debt. NFT = Asked amount + debt;

{% hint style="warning" %}
If a user borrows again, or if an auction ends, and before the user claims the NFT, the user borrows more, the auction and listing will get cancelled, the eth will get returned to the buyer, and the user will have to create a new listing.&#x20;
{% endhint %}

## View Methods

### getDebtId

```
function getDebtId(address nftAsset, uint256 tokenId) 
external view override returns (uint256)
```

Gets the id of the debt listing created.

#### Call Params

| Name     | Type    | Description                                  |
| -------- | ------- | -------------------------------------------- |
| nftAsset | address | the address of the borrowed underlying asset |
| tokenId  | uint256 | the tokenId of the underlying borrowed asset |

#### Return Values

| Type    | Description                                                                                                          |
| ------- | -------------------------------------------------------------------------------------------------------------------- |
| uint256 | returns the id of the debt listing created by the borrower. If 0 is returned means that there is no listing created. |

### getDebt

```
function getDebt(uint256 debtId) 
external view override returns (DataTypes.DebtMarketListing memory sellDebt)
```

It will return the struct containing the params used to create the debt listing.

#### Call Params

|        |         |                                                |
| ------ | ------- | ---------------------------------------------- |
| debtId | uint256 | The id of the listing created to sell the debt |

#### Return Values

|                             |                                                                       |
| --------------------------- | --------------------------------------------------------------------- |
| DataTypes.DebtMarketListing | A struct containing all the variables used to create the debt listing |

### getDebtIdTracker

```
function getDebtIdTracker() 
external view override returns (CountersUpgradeable.Counter memory)
```

It will return the next number to be used to create a debt listing.

#### Return Values

| Type                        | Description                                           |
| --------------------------- | ----------------------------------------------------- |
| CountersUpgradeable.Counter | an integer with the next number to be used as debtId. |

## Write Methods

### createDebtListing

```
createDebtListing(
    address nftAsset,
    uint256 tokenId,
    uint256 sellPrice,
    address onBehalfOf,
    uint256 startBiddingPrice,
    uint256 auctionEndTimestamp
  ) 
external override nonReentrant nonDuplicatedDebt(nftAsset, tokenId) 
onlyOwnerOfBorrowedNft(nftAsset, tokenId)
```

This function will allow the borrower to create his selling position. The user can choose if he wants a Fixed Price, an Auction, or both. In the case of both, if someone pays the fixed price or bids above it, he will become the new owner of the debt.

{% hint style="info" %}
**Example:** Bob borrowed 0.3ETH using mfer 1318 as collateral.

He decides that he wants to sell his position for 0.7ETH.

A new buyer, Alice, appears and pays the 0.7ETH making him the new owner.&#x20;

Bobs will get his 0.7ETH + 0.3ETH(he has previously asked for loan) = 1ETH

Alice paid 0.7ETH and has minted Bob's debt. She must pay the debt first if she wants to withdraw the NFT.&#x20;
{% endhint %}

#### Call Params

| Name                | Type    | Description                                  |
| ------------------- | ------- | -------------------------------------------- |
| nftAsset            | address | the address of the borrowed underlying asset |
| tokenId             | uint256 | the tokenId of the underlying borrowed asset |
| sellPrice           | uint256 | the amount the user wants for him            |
| onBehalfOf          | adress  | the wallet that will receive the funds       |
| startBiddingPrice   | uint256 | the amount to start an auction               |
| auctionEndTimestamp | uint256 | when will the auction end                    |

### cancelDebtListing

```
function cancelDebtListing(
    address nftAsset,
    uint256 tokenId
) external override nonReentrant debtShouldExistGuard(nftAsset, tokenId)
```

This function will cancel the debt listing if it exists. If a user borrows more, automatically, his listing will be cancelled, even if a user bought it but did not claim it. The idea is to prevent the user from borrowing more and front-run the new owner.

#### Call Params

| Name     | Type    | Description                                  |
| -------- | ------- | -------------------------------------------- |
| nftAsset | address | the address of the borrowed underlying asset |
| tokenId  | uint256 | the tokenId of the borrowed underlying asset |

### buy

```
function buy(
    address nftAsset,
    uint256 tokenId,
    address onBehalfOf,
    uint256 amount
  ) external override nonReentrant debtShouldExistGuard(nftAsset, tokenId)
```

If a buyer decides to pay the fixed price and become the new owner, this is the function to call.

#### Call Params

| Name       | Type    | Description                                  |
| ---------- | ------- | -------------------------------------------- |
| nftAsset   | address | the address of the borrowed underlying asset |
| tokenId    | uint256 | the tokenId of the borrowed underlying asset |
| onBehalfOf | address | the address that will get the debt and uNFT  |
| amount     | uint256 | the amount to pay in wei                     |

### bid

```
function bid(
    address nftAsset,
    uint256 tokenId,
    uint256 bidPrice,
    address onBehalfOf
  ) external override nonReentrant debtShouldExistGuard(nftAsset, tokenId)
```

The bid function will allow the user to bid on auctions listed by the borrowers.

{% hint style="info" %}
If the bid surpasses the fixed price (in case it has mixed auctions and fixed price), the debt will automatically work like a buy, making the bidder the new owner.
{% endhint %}

#### Call Params

| Name       | Type    | Description                                          |
| ---------- | ------- | ---------------------------------------------------- |
| nftAsset   | address | the address of the borrowed underlying asset         |
| tokenId    | uint256 | the tokenId of the borrowed underlying asset         |
| bidPrice   | uint256 | the bid amount in wei the user wants to offer.       |
| onBehalfOf | address | the address that will get the debt and uNFT (if won) |

### claim

```
function claim(
    address nftAsset,
    uint256 tokenId,
    address onBehalfOf
  ) external override nonReentrant debtShouldExistGuard(nftAsset, tokenId)
```

When an auction ends, the winner can claim the debt. The debt and the uNFT will be burned and minted from the seller to the new owner (buyer).

{% hint style="warning" %}
If the borrower decides to borrow more after the auction ends and before the buyer claims. The auction will get cancelled, the buyer will get his ETH back, and the borrower will increase his debt.
{% endhint %}

#### Call Params

| Name       | Type    | Description                                  |
| ---------- | ------- | -------------------------------------------- |
| nftAsset   | address | the address of the borrowed underlying asset |
| tokenId    | uint256 | the tokenId of the borrowed underlying asset |
| onBehalfOf | address | the address that will get the debt and uNFT  |


# LockeyManager

This contract will manage the percentage that Lockey NFT holders can get if configured. Currently, the amount is 100%, which means no discounts are having an effect when the user does a buyout on an auction or a debt market listing.

{% hint style="warning" %}
The borrower can end up "losing" a portion of his amount if the Lockey percentages change.\
\
Example: the Lockey holders can have a 3% discount when buying out an NFT on an auction.\
\
If the buyout price is 50ETH, means a regular buyer will pay the whole amount but a Lockey holder will pay 48.5ETH.
{% endhint %}

## View Methods

### getLockeyDiscountPercentage

`function getLockeyDiscountPercentage() external view returns (uint256)`

The function returns the percentage that the Lockey holder will pay to a buyout on an auction.

{% hint style="info" %}
for the example above, if the Lockey holder has a 3% discount it means the function will return 97%, using this way will minimize the calculations to achieve the right amount.
{% endhint %}

#### Return Values

| Type    | Description                                     |
| ------- | ----------------------------------------------- |
| uint256 | the percentage amount a Lockey holder will pay. |

### getLockeyDiscountPercentageOnDebtMarket

`function getLockeyDiscountPercentageOnDebtMarket() external view returns (uint256)`

The function returns the percentage that the Lockey holder will pay for a debt market listing.\
It will follow the same logic as the example above.

#### Return Values

| Type    | Description                                     |
| ------- | ----------------------------------------------- |
| uint256 | the percentage amount a Lockey holder will pay. |

## Write Methods

### setLockeyDiscountPercentage

`function setLockeyDiscountPercentage(uint256 discountPercentage) external onlyPoolAdmin`

The percentage to be discounted can only be set by the PoolAdmin, this is the percentage that the Lockey holders can have for an auction. By default, the number should be 100%

#### Call Params

| Name               | Type    | Description                                                                   |
| ------------------ | ------- | ----------------------------------------------------------------------------- |
| discountPercentage | uint256 | default = 100 any value lower than that will make the lockey holder pay less. |

### setLockeyDiscountPercentageOnDebtMarket

`function setLockeyDiscountPercentageOnDebtMarket(uint256 discountPercentage) external onlyPoolAdmin`

The percentage to be discounted can only be set by the PoolAdmin, this is the percentage that the Lockey holders can have for a debt market listing purchase. By default, the number should be 100%

#### Call Params

| Name               | Type    | Description                                                                   |
| ------------------ | ------- | ----------------------------------------------------------------------------- |
| discountPercentage | uint256 | default = 100 any value lower than that will make the lockey holder pay less. |


# Adapters

Adapters allow for the integration of several external liquidation markets, and are based on a BaseAdapter contract that contains generic liquidation functionality. As of today, Unlockd's primary adapter used for liquidations is Reservoir

## Reservoir Adapter

Reservoir adapter aims at leveraging Reservoir's powerful infrastructure for trading NFTs across major marketplaces and chains. It liquidates NFT's seeking for the best offers accross different marketplaces, such as OpenSea, LooksRare and X2Y2. The liquidation process is as follows:

1. Trigger \`liquidateReservoir()\`, passing the specific calldata which holds the transfer of the NFT to reservoir's Router contract

{% hint style="info" %}
\`liquidateReservoir()\` is note permissionless, effectively enabling only Unlockd specific addresses to execute liquidations on Reservoir
{% endhint %}

2. Validate the calldata specifically designed to:
   1. Transfer the NFT in a safely manner to the specific reservoir module the NFT should be liquidated in
   2. Execute Reservoir router's \`execute()\` function with the specific calldata
3. Transfer the NFT to Reservoir's target module, where the NFT will be "automatically" liquidated
4. Validate the amount liquidated matches the expected liquidation price
5. Settle liquidation

### Write methods

`function liquidateReservoir(address nftAsset, address reserveAsset, bytes calldata data, uint256 expectedLiquidateAmount) external`

Liquidates an unhealthy loan in reservoir.

#### Call params

| Name                    | Type    | Description                                                               |
| ----------------------- | ------- | ------------------------------------------------------------------------- |
| nftAsset                | address | The address of the NFT to be liquidated                                   |
| reserveAsset            | address | The reserve for the liquidation                                           |
| data                    | bytes   | The data to execute, containing the execution data for reservoir's module |
| expectedLiquidateAmount | uint256 | The amount the NFT is expected to be exchanged for                        |


# uNFT Registry

UNFTRegistry.sol

This contract is where we store the information regarding the uNFTs. \
The proxies and the implementations are created and stored.

## View Methods

### getUNFTAddresses

`function getUNFTAddresses(address nftAsset) external view returns (address uNftProxy, address uNftImpl)`

Returns the uNFT address

#### Call Params

| Name     | Type    | Description                             |
| -------- | ------- | --------------------------------------- |
| nftAsset | address | The address of the underlying NFT asset |

#### Return Values

| Name      | Type    | Description                                                        |
| --------- | ------- | ------------------------------------------------------------------ |
| uNftProxy | address | the address of the proxy created for the underlying asset          |
| uNftImpl  | address | the address of the implementation created for the underlying asset |

### getUNFTAddressesByIndex

`function getUNFTAddressesByIndex(uint16 index) external view returns (address uNftProxy, address uNftImpl)`

Returns the uNFT proxy and implementation address by index

#### Call Param

| Name  | Type   | Description    |
| ----- | ------ | -------------- |
| index | uint16 | the uNFT index |

#### Return Values

| Name      | Type    | Description                                                        |
| --------- | ------- | ------------------------------------------------------------------ |
| uNftProxy | address | the address of the proxy created for the underlying asset          |
| uNftImpl  | address | the address of the implementation created for the underlying asset |

### getUNFTAssetList

`function getUNFTAssetList() external view returns (address[])`

Returns the list of uNFTs addresses.&#x20;

#### Return Values

| Type                            | Description                                        |
| ------------------------------- | -------------------------------------------------- |
| array of addresses (address\[]) | the addresses stored in the contract when created. |

### allUNFTAssetLength

`function allUNFTAssetLength() external view returns (uint256)`

Returns the length of the list of uNFTs addresses.

#### Return Values

| Type      | Description                         |
| --------- | ----------------------------------- |
| `uint256` | the length of addresses in the list |

## Write Methods

### createUNFT

`function createUNFT(address nftAsset) external returns (address uNftProxy)`

Create uNFT proxy and implement it, then initialize it.

#### Call Param

| Name     | Type    | Description                                     |
| -------- | ------- | ----------------------------------------------- |
| nftAsset | address | The address of the underlying asset of the UNFT |

#### Return Values

| Name      | Type    | Description                                               |
| --------- | ------- | --------------------------------------------------------- |
| uNftProxy | address | the address of the proxy created for the underlying asset |


# LendingPool Protocol

The address deployed.

<table><thead><tr><th width="272.3333333333333">Contracts</th><th width="247">Goerli</th><th>Ethereum</th></tr></thead><tbody><tr><td>LendPoolAddressesProvider</td><td>0x904F88956b006e46fF8ba3102f154f00b5A78070</td><td>0xE6cd031FB0D9A79FD8CD3035B9228F78ff459B07</td></tr><tr><td>LendPool</td><td>0xD0d757a6a79830e8B891E631577c92dFcDd7fC15</td><td>0xFC7f036a8FB66D031675239413F9179A82932a53</td></tr><tr><td>LendPoolLoan</td><td>0xeE74e1E16B82275CD7bDdb27dd67d92018B322ee</td><td>0x00da789CEBF4A0da965FbcB9e4d72F1A15c67Eb6</td></tr><tr><td>UNFTRegistry</td><td>0xF6bA9b7ce803fd04355673F782FA719A19c902Fb</td><td>0x255f25335662c88Fcc7deC402cADf2f4f0E08300</td></tr><tr><td>UNFT</td><td>0x4B336eFE7299042305f0c39C7B44049df22e2f99</td><td>0x1014BBC1ED63CC49e6118769D412E715A1cEbCD8</td></tr><tr><td>UToken</td><td>0x2DF0b8b3e7b85f49431e6fe3e4f6Df63E76FEd49</td><td>0x94B1010EAF40edA5080936B224F4618B67735807</td></tr><tr><td>DebtToken</td><td>0x19Ec9832c8C2336D43357615E1A5cbd7dFCe8510</td><td>0xBFf0af4f649f8a1d8420FcDD0D405dDDE89C8851</td></tr><tr><td>ReserveOracle</td><td>0xf3A31679d22D0C320ca56f8E4bcE2274e34BF93A</td><td>0x2954B6ce3E9788e2A6dE603358918f2eb067AABa</td></tr><tr><td>NFTOracle</td><td>0x09B4d089424DD0167e92c850300417C343d84C7C</td><td>0xed1a46EBE904dD6562f5F20A515009752Fb5bAdE</td></tr><tr><td>WETHGateway</td><td>0xEF4ce9745922bB864B220bf58DE24153307810DE</td><td>0x66CD472E4404D0C62d7068b4D69e28D5Ed6C32c2</td></tr><tr><td>PunkGateway</td><td>0x8e864aD71d5E7F9C193697362e68a532CC7A0086</td><td>0x2540b104310EFa795DE0a9247Ba3942b71385251</td></tr><tr><td>UnlockdProtocolDataProvider</td><td>0xC8ee57F3d3c077710639965c554716bcb458c8f3</td><td>0x93fd3eB6e8A3aeDc50b5fdF1C0Ee6aE621BB3Cec</td></tr><tr><td>UIPoolDataProvider</td><td>0x2d77b7284F02b94e168560284220e0Ab56fCAB09</td><td>0xD726b93865393fb3B345C66Da3EB5999B5aC4754</td></tr></tbody></table>


# Best Practices

As a developer working with the Unlockd Protocol or any DeFi project, it is crucial to follow best practices to ensure the security, stability, and efficiency of your integration.

## Code Quality

1. **Smart contract audits**: Before deploying any smart contract to the mainnet, ensure it has been thoroughly reviewed and audited by reputable security firms. This minimizes the risk of vulnerabilities and exploits.
2. **Code modularity and readability**: Write modular and well-structured code to make it easy for other developers to understand, review, and contribute to your project. This includes using appropriate naming conventions, commenting, organizing your codebase, and following established programming paradigms.
3. **Testing**: Implement comprehensive test suites for your smart contracts, including unit tests, integration tests, and end-to-end tests. This ensures that your code behaves as expected and helps catch potential bugs or issues.
4. **Continuous integration and deployment**: Set up a CI/CD pipeline to automatically build, test, and deploy your code. This helps catch integration issues early and streamlines the development process.

## Interaction with External Contracts

1. **Use trusted and audited contracts**: When interacting with third-party contracts or libraries, ensure they have been audited and are widely trusted within the ecosystem.
2. **Handle external contract calls safely**: Be cautious when making external contract calls. Assume that any external contract can be malicious, and handle reentrancy attacks, untrusted callbacks, and gas limits accordingly. Use the "checks-effects-interactions" pattern to minimize risks.
3. **Manage contract upgrades**: Plan for the potential need to upgrade your smart contracts in the future. Design your contracts to be upgradeable or use proxy patterns, but always keep in mind the trade-offs and security implications.

## Gas Optimization

1. **Optimize for gas usage**: Write efficient smart contract code to minimize gas costs for users. This may include using appropriate data structures, minimizing storage writes, and taking advantage of compiler optimizations.
2. **Batch transactions**: When possible, batch multiple transactions together to reduce gas costs and improve the overall user experience.
3. **Monitor gas prices**: Keep track of the current gas prices and suggest optimal gas fees to users for a balance between cost and transaction speed.

## Decentralization and Governance

1. **Embrace decentralization**: Strive to decentralize the control and decision-making processes of your DeFi project. This increases trust and helps prevent single points of failure.
2. **Implement governance mechanisms**: Incorporate governance tokens and mechanisms to give users a say in the development and management of your platform.
3. **Ensure transparency**: Make your project's code, documentation, and governance processes open and transparent to the community. This fosters trust and encourages engagement from users and developers alike.


# Security and Risk Management

Prioritizing security and risk management is crucial when working with DeFi protocols. Here are some guidelines to consider:

## Smart Contract Security

1. **Use established patterns**: Whenever possible, use established and secure design patterns for your smart contracts. For example, use the OpenZeppelin library for implementing ERC20 tokens or standard access control mechanisms.
2. **Minimize complexity**: Keep your smart contracts as simple as possible. Complexity increases the chances of introducing vulnerabilities and makes it harder to audit and verify the code's correctness.
3. **Monitor and respond to vulnerabilities**: Stay informed about new vulnerabilities discovered in the DeFi ecosystem and apply patches or updates as needed. Be prepared to react to potential threats to your smart contracts.
4. **Use formal verification**: Apply formal verification techniques to validate the correctness of your smart contract code. This can help identify potential issues and ensure that the contracts meet their intended specifications.
5. **Secure randomness**: If your smart contract requires random numbers, use secure and decentralized sources of randomness, such as Chainlink's VRF (Verifiable Random Function) or similar solutions

## User Protection

1. **Ensure proper access control**: Implement appropriate access controls for your smart contracts, such as role-based access control (RBAC) or the use of multi-signature wallets for critical functions.
2. **Provide transparent information**: Clearly communicate the risks and mechanics of your platform to users. This includes providing thorough documentation, terms of service, and risk disclaimers.
3. **Implement emergency mechanisms**: Design your smart contracts with emergency mechanisms, such as circuit breakers or pause functions, to halt operations in case of an unexpected issue or vulnerability.
4. **Protect user privacy**: Consider incorporating privacy-enhancing technologies like zero-knowledge proofs (ZKPs) to protect user data and transactions.
5. **Educate users**: Offer resources and guidance to help users understand the importance of safe practices, such as using hardware wallets, keeping private keys secure, and enabling two-factor authentication (2FA).

## Risk Management

1. **Monitor platform activity**: Regularly monitor the activity and performance of your DeFi platform. Set up alerts and monitoring tools to track unusual behavior or potential exploits.
2. **Establish risk management processes**: Develop clear processes and procedures for managing risks within your platform, such as collateral management, liquidation policies, and interest rate adjustments.
3. **Consider insurance**: Encourage users to utilize smart contract insurance services like Nexus Mutual or Bridge Mutual to protect their assets against potential losses from exploits or vulnerabilities.
4. **Perform stress tests and simulations**: Conduct stress tests and simulations on your platform to evaluate its resilience under extreme market conditions or high network congestion.
5. **Maintain a bug bounty program**: Implement a bug bounty program to incentivize responsible disclosure of vulnerabilities and security issues by external researchers. Find ours [here](https://immunefi.com/bounty/unlockd/).


# Introduction

The Unlockd Protocol is a decentralized finance (DeFi) platform that enables borrowing and lending of Real-World Assests (RWAs) in the form of non-fungible tokens and other digital assets. It provides a comprehensive set of smart contracts and libraries that facilitate secure and efficient management of loans, orders, auctions, and asset transactions.

The protocol is designed to be modular and extensible, allowing developers to build upon its core functionality and integrate it with various marketplaces and platforms. By leveraging the power of blockchain technology and smart contracts, Unlockd aims to revolutionize how RWAs and digital assets are utilized in the DeFi ecosystem.

<figure><img src="https://1802212726-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeqGi7JVGKRiZ8CDr4vSm%2Fuploads%2FRoIefCPtCJs9DYtOGjLI%2Fimage.png?alt=media&amp;token=2f1e9baa-2751-44c2-83c1-ea5103956310" alt=""><figcaption></figcaption></figure>

### Key Features and Benefits

* **Borrowing and Lending**: Unlockd enables users to borrow against RWAs and other digital assets, as well as earn yield providing liquidity.
* **Market Functionality**: The protocol supports various market-related functionalities, such as placing orders, participating in auctions, and executing buy-and-sell transactions.
* **Secure and Auditable**: Smart contracts secure all transactions and interactions with the protocol and record them on the blockchain, ensuring transparency and immutability.
* **Modular Architecture**: Unlockd follows a modular design pattern, allowing developers to extend and customize the protocol to suit their needs quickly.
* **Integration with External Platforms**: The protocol provides adapters and interfaces to integrate with external marketplaces and platforms, such as Reservoir, enabling seamless interaction with the broader RWA/NFT ecosystem.
* **Efficient Asset Management**: Unlockd offers efficient management of digital assets through its vault and token contracts, ensuring secure storage and handling of funds.

### Target Audience and Use Cases

The Unlockd Protocol caters to a wide range of users and developers in the DeFi and RWA space:

* **RWAs Owners**: Individuals and institutions holding RWAs can utilize Unlockd to unlock the liquidity of their assets, borrow against them, or participate in lending and market activities.
* **DeFi Developers**: Developers can leverage Unlockd's modular architecture and extensive libraries to build and deploy their own DeFi applications and marketplaces.
* **Traders and Investors**: Traders and investors can participate in the Unlockd ecosystem by engaging in borrowing, lending, and market activities, taking advantage of the protocol's secure and efficient trading mechanisms.
* **Marketplace Operators**: Existing RWA marketplaces can integrate with Unlockd to offer their users additional features and liquidity options.
* **DeFi Protocols**: Other DeFi protocols can integrate with Unlockd to expand their offerings and provide RWA-related services to their users.

Some potential use cases for the Unlockd Protocol include:

* Collateralized RWA borrowing
* Fractional ownership and liquidity provisioning for high-value RWAs
* Decentralized marketplaces for RWAs trading
* Automated market makers (AMMs) for RWAs
* RWA-based derivatives and synthetic assets

The Unlockd Protocol aims to empower developers and users in the DeFi and RWA ecosystem by providing a robust and flexible infrastructure for building innovative applications and financial products.


# Unlockd

`Unlockd.sol` is the main entry point for the Unlockd Protocol. It serves as a proxy dispatcher, routing calls to the appropriate module contracts based on the provided module ID.

### Key variables:

`_moduleLookup`: A mapping that stores the implementation address for each module ID.

`_proxyLookup`: A mapping that stores the proxy address for each module ID (only for single-proxy modules).

### Key functions:

<pre class="language-solidity"><code class="lang-solidity"><strong>_constructor(address aclManager, address installerModule)
</strong></code></pre>

Initializes the contract with the ACL manager and installer module addresses. It also sets up the initial module and proxy lookups.

### Parameters:

`aclManager`: The address of the ACL manager contract.

`installerModule`: The address of the installer module contract.

***

```solidity
function moduleIdToImplementation(
    uint256 moduleId
) external view returns (address)
```

Returns the implementation address for a given module ID.

### Parameters:

`moduleId`: The ID of the module.

### Returns:&#x20;

The implementation address of the module.

***

```solidity
function moduleIdToProxy(
    uint256 moduleId
) external view returns (address)
```

Returns the proxy address for a given module ID.

### Parameters:

`moduleId`: The ID of the module.

### Returns:&#x20;

The proxy address of the module.

***

```solidity
function dispatch() external reentrantOK
```

It dispatches the incoming call to the corresponding module contract based on the caller's trusted module ID and implementation address. It uses assembly to extract the module ID and implementation address from the caller's storage slot and delegate the call to the appropriate module contract.


# BaseCore

`BaseCore.sol` contains the base logic for the proxy contracts used in the Unlockd Protocol. It provides functions for creating and managing module proxies and handling module-specific logic.

### Key variables:

`_moduleLookup`: A mapping that stores the implementation address for each module ID.

`_proxyLookup`: A mapping that stores the proxy address for each module ID (only for single-proxy modules).

`_trustedSenders`: A mapping that stores the trusted sender information for each proxy address, including the module ID and implementation address (only for external single-proxy modules).

### Key functions:

```solidity
function _createProxy(
    uint256 proxyModuleId
) internal returns (address)
```

Creates a new proxy contract for the specified module ID. It deploys a new instance of the `UnlockdMinimalProxy` contract and stores the proxy address in the `_proxyLookup` mapping if the module ID is within the range of external single-proxy modules. It also updates the `_trustedSenders` mapping with the module ID and implementation address for the proxy.

### Parameters:

`proxyModuleId`: The ID of the module for which to create a proxy.

### Returns:&#x20;

The address of the created proxy contract.

***

```solidity
function callInternalModule(
    uint256 moduleId,
    bytes memory input
  ) internal returns (bytes memory)
```

Performs a delegatecall to the specified module contract with the provided input data. It retrieves the module implementation address from the `_moduleLookup` mapping and delegates the call using assembly. If the call fails, it reverts with the returned error data.

### Parameters:

`moduleId`: The ID of the module to call.

`input`: The input data for the module call.

### Returns:&#x20;

The return data from the module call.


# BaseCoreModule

`BaseCoreModule.sol` serves as the base contract for each module in the Unlockd Protocol. It inherits from `BaseCore.sol` and provides additional functionality specific to modules.

### Key variables:

`moduleId`: The unique identifier of the module.

`moduleVersion`: The version of the module.

### Key functions:

```solidity
constructor(uint256 moduleId_, bytes32 moduleVersion_)
```

Initializes the contract with the module ID and version.

### Parameters:

`moduleId_`: The ID of the module.

`moduleVersion_`: The version of the module.

***

```solidity
function unpackTrailingParamMsgSender() 
internal pure returns (address msgSender)
```

Retrieves the original sender address from the calldata using assembly.

### Returns:&#x20;

The original sender's address.

***

```solidity
function unpackTrailingParams() 
internal pure returns (
    address msgSender, 
    address proxyAddr
)
```

Retrieves the original sender address and proxy address from the calldata using assembly.

### Returns:

`msgSender`: The original sender's address.

`proxyAddr`: The proxy address.

***

```solidity
function _checkHasUnlockdWallet(
    address msgSender
) internal view 
```

Description: Checks if the sender has a valid Unlockd wallet by querying the wallet registry contract.

### Parameters:

`msgSender`: The address of the sender to check.


# Installer

`Installer.sol` Is a module contract that is responsible for installing other modules in the Unlockd Protocol.

### Key functions:

```solidity
function installModules(
    address[] memory moduleAddrs
) external onlyAdmin
```

Installs multiple modules by providing an array of module addresses.

### Parameters:

`moduleAddrs`: An array of module addresses to be installed.

### Emits:&#x20;

`InstallerInstallModule` event for each installed module.


# Manager

`Manager.sol` is a module contract that provides management functionality for the Unlockd Protocol. It allows authorized users to set and update various protocol parameters. e

Key functions:

```solidity
function setSafeERC721(address safeERC721)
```

Sets the address of the SafeERC721 contract. Only callable by the admin role.

### Parameters:

`safeERC721`: The address of the SafeERC721 contract to be set.

***

```solidity
function getSafeERC721() external view returns (address)
```

Returns the address of the SafeERC721 contract.

***

```solidity
function setReserveOracle(address oracle) external onlyAdmin
```

Sets the address of the reserve oracle contract. Only callable by the admin role.

### Parameters:

`oracle`: The address of the reserve oracle contract to be set.

***

```solidity
function getReserveOracle() external view returns (address)
```

Returns the address of the reserve oracle contract.

***

```solidity
function setSigner(address signer) external onlyAdmin
```

Sets the address of the signer used for signature verification. Only callable by the admin role.

### Parameters:

`signer`: The address of the signer to be set.

***

```solidity
function getSigner() external view returns (address)
```

Returns the address of the signer used for signature verification.

***

```solidity
function setWalletRegistry(address walletRegistry) external onlyAdmin
```

Sets the address of the wallet registry contract. Only callable by the admin role.

### Parameters:

`walletRegistry`: The address of the wallet registry contract to be set.

***

```solidity
function getWalletRegistry() external view returns (address)
```

Returns the address of the wallet registry contract.

***

```solidity
function setAllowedControllers(
    address allowedControllers
) external onlyAdmin
```

Sets the address of the allowed controller contract. Only callable by the admin role.

### Parameters:

`allowedControllers`: The address of the allowed controller contract to be set.

***

```solidity
function getCollectionReserveType(
    address collection
 ) external view returns (Constants.ReserveType)
```

Returns the address of the allowed controller contract.

***

```solidity
function allowCollectionReserveType(
    address collection,
    Constants.ReserveType reserveType
  ) external onlyAdmin
```

Allows a specific collection and reserve type combination. Only callable by the admin role.

### Parameters:

`collection`: The address of the collection to be allowed.

`reserveType`: The reserve type to be associated with the collection.

***

```solidity
function getCollectionReserveType(
    address collection
  ) external view returns (Constants.ReserveType)
```

Returns the reserve type associated with a given collection.

### Parameters:

`collection`: The address of the collection.

***

```solidity
function setUTokenVault(address uTokenVault) external onlyAdmin
```

Sets the address of the UTokenVault contract. Only callable by the admin role.

### Parameters:

`uTokenVault`: The address of the UTokenVault contract to be set.

***

```solidity
function getUTokenVault() external view returns (address)
```

Returns the address of the UTokenVault contract.

***

```solidity
function addMarketAdapters(
    address adapter, 
    bool active
) external onlyGovernance
```

Adds or removes a market adapter from the allowed list. Only callable by the governance role.

### Parameters:

`adapter`: The address of the market adapter to be added or removed.

`active`: A boolean indicating whether the adapter should be active or not.

***

```solidity
function isMarketAdapterActive(address adapter) external view returns (uint256)
```

Returns the status of a market adapter (active or disabled).

### Parameters:

`adapter`: The address of the market adapter.

***

```solidity
function emergencyFreezeLoan(bytes32 loanId) external onlyEmergency
function emergencyActivateLoan(bytes32 loanId) external onlyEmergency
function emergencyBlockLoan(bytes32 loanId) external onlyEmergency
```

Emergency functions to freeze, activate, or block a loan. Only callable by the emergency admin role.

### Parameters:

`loanId`: The ID of the loan to be frozen, activated, or blocked.

***

```solidity
function emergencyUpdateEndTimeAuction(
    bytes32 orderId,
    uint40 newEndTime
  ) external onlyEmergency 
```

Emergency function to update the end time of an auction. Only callable by the emergency admin role.

### Parameters:

`orderId`: The ID of the order associated with the auction.

`newEndTime`: The new end time for the auction.


# Action

`Action.sol` is a module contract that handles various user actions within the Unlockd Protocol, such as borrowing, repaying, and unlocking assets.

### Key functions:

```solidity
function getLoan(
    bytes32 loanId
) external view returns (DataTypes.Loan memory)
```

Returns the details of a loan given its ID.

### Parameters:

`loanId`: The ID of the loan to retrieve.

***

```solidity
function getAmountToRepay(
    bytes32 loanId
) external view returns (uint256 amount)
```

Returns the amount required to repay a loan.

### Parameters:

`loanId`: The ID of the loan to calculate the repayment amount for.

***

```solidity
function borrow(
    uint256 amount,
    DataTypes.Asset[] calldata assets,
    DataTypes.SignAction calldata signAction,
    DataTypes.EIP712Signature calldata sig
) external
```

Allows users to borrow assets using the specified loan and collateral. It validates the signature, updates the loan state, and performs the necessary actions to borrow the assets.

### Parameters:

`amount`: The amount to borrow.

`assets`: An array of assets to be used as collateral.

`signAction`: The signed action data.

`sig`: The EIP-712 signature for the borrow operation.

***

```solidity
function repay(
    uint256 amount,
    DataTypes.SignAction calldata signAction,
    DataTypes.EIP712Signature calldata sig
) external
```

Allows users to repay a loan and unlock assets if the health factor is above 1. It validates the signature, updates the loan state, transfers the repayment amount, and unlocks the assets if the health factor is above 1 or the total amount repaid.

### Parameters:

`amount`: The amount to repay.

`signAction`: The signed action data.

`sig`: The EIP-712 signature for the repay operation.

## Signature

#### `signAction` (type: `DataTypes.SignAction`), it contains the following fields:

`loan` (type: `DataTypes.SignLoanConfig`): The loan configuration data, including the loan ID, aggregated loan price, LTV, liquidation threshold, total assets, nonce, and deadline.

`assets` (type: `bytes32[]`): An array of assetIDs involved in the action.

`underlyingAsset` (type: `address`): The address of the underlying asset for the loan.

`nonce` (type: `uint256`): The nonce value is used to ensure the uniqueness of the signature and prevent replay attacks.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.

#### `sig` (type: `DataTypes.EIP712Signature`), it contains the following fields:

`v` (type: `uint8`): The recovery ID of the signature.

`r` (type: `bytes32`): The first 32 bytes of the signature.

`s` (type: `bytes32`): The second 32 bytes of the signature.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.


# SellNow

`SellNow.sol` is a module contract that provides functionality for selling NFTs within the Unlockd Protocol. It allows users to sell their NFTs either through a direct sale or force-selling them using the protocol's backend in case of liquidation.

### Key functions:

```solidity
function forceSell(
    DataTypes.Asset calldata asset,
    DataTypes.SignSellNow calldata signSellNow,
    DataTypes.EIP712Signature calldata sig
) external onlyAuctionAdmin
```

Allows the auction admin to force-sell an NFT managed by the protocol's bot. It validates the signature, retrieves the loan details, validates the force-sell action, approves the sale, executes the sale using the market adapter, repays the debt, and distributes the funds to the asset owner.

### Parameters:

`asset`: The asset to be force-sold.

`signSellNow`: The signed sell now data.

`sig`: The EIP-712 signature for the force-sell operation.

***

```solidity
function sell(
    DataTypes.Asset calldata asset,
    DataTypes.SignSellNow calldata signSellNow,
    DataTypes.EIP712Signature calldata sig
) external
```

Allows users to sell their NFTs directly. It validates the signature, retrieves the user's Unlockd wallet and protocol owner addresses, validates the sell action, approves the sale, executes the sale using the market adapter, repays the debt (if any), and distributes the funds to the user.

### Parameters:

`asset`: The asset to be sold.

`signSellNow`: The signed sell now data.

`sig`: The EIP-712 signature for the sell operation.

## Signature

#### `signSellNow` (type: `DataTypes.SignSellNow`), it contains the following fields:

`loan` (type: `DataTypes.SignLoanConfig`): The loan configuration data, including the loan ID, aggregated loan price, LTV, liquidation threshold, total assets, nonce, and deadline.

`assetId` (type: `bytes32`): The ID of the asset being sold.

`marketAdapter` (type: `address`): The address of the market adapter used for the sell now action.

`marketApproval` (type: `address`): The address for market approval.

`marketPrice` (type: `uint256`): The market price of the asset.

`underlyingAsset` (type: `address`): The address of the underlying asset.

`from` (type: `address`): The address from which the sell now action is initiated.

`to` (type: `address`): The address to which the asset is being sold.

`data` (type: `bytes`): Additional data for the sell now action.

`value` (type: `uint256`): The value being sent with the sell now action.

`nonce` (type: `uint256`): The nonce value is used to ensure the uniqueness of the signature and prevent replay attacks.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.

#### `sig` (type: `DataTypes.EIP712Signature`), it contains the following fields:

`v` (type: `uint8`): The recovery ID of the signature.

`r` (type: `bytes32`): The first 32 bytes of the signature.

`s` (type: `bytes32`): The second 32 bytes of the signature.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.


# BuyNow

`BuyNow.sol` is a module contract that enables users to buy assets within the Unlockd Protocol. It provides functionality for instant asset purchases, allowing users to buy assets using a combination of their own funds and borrowed funds from the protocol.

### Key functions:

```solidity
function getCalculations(
    DataTypes.SignBuyNow calldata signBuyMarket
) external pure returns (uint256, uint256)
```

Calculates the minimum amount required and the maximum amount that can be borrowed for a buy now operation based on the buy now data.

### Parameters:

`signBuyMarket`: The signed buy now data.

### Returns:

The minimum amount required from the user.

The maximum amount that can be borrowed.

***

```solidity
function buy(
    uint256 amount,
    DataTypes.SignBuyNow calldata signBuyMarket,
    DataTypes.EIP712Signature calldata sig
) external 
```

Allows users to perform a buy now operation, purchasing an asset using the specified amount and creating a loan if necessary. It validates the signature, retrieves the user's Unlockd wallet and protocol owner addresses, updates the reserve state, transfers the user's contribution to the market adapter, creates a loan if necessary, and purchases the asset using the market adapter.

### Parameters:

`amount`: The amount to contribute towards the purchase.

`signBuyMarket`: The signed buy now data.

`sig`: The EIP-712 signature for the buy operation.

## Signature

#### `signBuyMarket` (type: `DataTypes.SignBuyNow`), it contains the following fields:

`asset` (type: `DataTypes.SignAsset`): The asset data, including the asset ID, collection address, token ID, price, nonce, and deadline.

`assetLtv` (type: `uint256`): The loan-to-value ratio of the asset.

`assetLiquidationThreshold` (type: `uint256`): The liquidation threshold of the asset.

`from` (type: `address`): The address from which the buy now action is initiated.

`to` (type: `address`): The address to which the asset is being bought.

`data` (type: `bytes`): Additional data for the buy now action.

`value` (type: `uint256`): The value being sent with the buy now action.

`marketAdapter` (type: `address`): The address of the market adapter used for the buy now action.

`marketApproval` (type: `address`): The address for market approval.

`marketPrice` (type: `uint256`): The market price of the asset.

`underlyingAsset` (type: `address`): The address of the underlying asset.

`nonce` (type: `uint256`): The nonce value is used to ensure the uniqueness of the signature and prevent replay attacks.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.

#### `sig` (type: `DataTypes.EIP712Signature`), it contains the following fields:

`v` (type: `uint8`): The recovery ID of the signature.

`r` (type: `bytes32`): The first 32 bytes of the signature.

`s` (type: `bytes32`): The second 32 bytes of the signature.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.


# Market

`Market.sol` is a module contract that handles market-related functionalities in the Unlockd Protocol. It allows users to create and manage orders, place bids, claim assets, and perform buy and sell operations.

### Key functions:

```solidity
function getOrder(
    bytes32 orderId
) external view returns (DataTypes.Order memory)
```

Returns the details of an order given its ID.

### Parameters:

`orderId`: The ID of the order to retrieve.

***

```solidity
function getMinBidPrice(
    bytes32 orderId,
    address underlyingAsset,
    uint256 aggLoanPrice,
    uint256 aggLtv
) external view returns (uint256 minBid)
```

Returns the minimum bid price for an order.

### Parameters:

`orderId`: The ID of the order.

`underlyingAsset`: The address of the underlying asset.

`aggLoanPrice`: The aggregated loan price.

`aggLtv`: The aggregated loan-to-value ratio.

***

```solidity
function getBuyNowPrice(
    bytes32 orderId,
    address underlyingAsset,
    uint256 aggLoanPrice,
    uint256 aggLtv
) external view returns (uint256 amount)
```

Returns the buy-now price for an order.

### Parameters:

`orderId`: The ID of the order.

`underlyingAsset`: The address of the underlying asset.

`aggLoanPrice`: The aggregated loan price.

`aggLtv`: The aggregated loan-to-value ratio.

***

```solidity
function create(
    address underlyingAsset,
    Constants.OrderType orderType,
    CreateOrderInput calldata config,
    DataTypes.SignMarket calldata signMarket,
    DataTypes.EIP712Signature calldata sig
) external
```

Allows users to create a new order. It validates the signature, retrieves the loan details, updates the loan state, validates the order creation, and creates a new order with the specified parameters.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`orderType`: The type of the order.

`config`: The configuration parameters for creating the order.

`signMarket`: The signed market data.

`sig`: The EIP-712 signature for the order creation.

***

```solidity
function cancel(bytes32 orderId) external
```

Allows the order owner to cancel an existing order. It retrieves the order and loan details, validates the cancellation action, refunds any existing bid, and deletes the order.

### Parameters:

`orderId`: The ID of the order to cancel.

***

```solidity
function bid(
    bytes32 orderId,
    uint128 amountToPay,
    uint128 amountOfDebt,
    DataTypes.SignMarket calldata signMarket,
    DataTypes.EIP712Signature calldata sig
) external 
```

Allows users to place a bid on an order. It validates the signature, retrieves the order and loan details, validates the bid action, transfers the bid amount, creates a new loan for the bidder if a debt is requested, refunds any existing bid, and updates the order with the new bid details.

### Parameters:

`orderId`: The ID of the order to bid on.

`amountToPay`: The amount to pay for the bid.

`amountOfDebt`: The amount of debt associated with the bid.

`signMarket`: The signed market data.

`sig`: The EIP-712 signature for the bid.

***

```solidity
function claim(
    bool claimOnUWallet,
    bytes32 orderId,
    DataTypes.SignMarket calldata signMarket,
    DataTypes.EIP712Signature calldata sig
) external
```

Allows users to claim assets from a completed order. It validates the signature, retrieves the order and loan details, validates the claim action, transfers the claimed amount, updates the loan state, and transfers the claimed assets to the winning bidder.

### Parameters:

`claimOnUWallet`: A flag indicating whether to claim the assets on the user's Unlockd wallet.

`orderId`: The ID of the order to claim assets from.

`signMarket`: The signed market data.

`sig`: The EIP-712 signature for the claim.

***

```solidity
function cancelClaim(
    bytes32 orderId,
    DataTypes.SignMarket calldata signMarket,
    DataTypes.EIP712Signature calldata sig
) external
```

Allows users to cancel a pending claim on an order. It validates the signature, retrieves the order and loan details, validates the claim cancellation action, and refunds the pending claim amount.

### Parameters:

`orderId`: The ID of the order associated with the claim to cancel.

`signMarket`: The signed market data.

`sig`: The EIP-712 signature for the claim cancellation.

***

```solidity
 function buyNow(
    bool claimOnUWallet,
    bytes32 orderId,
    uint256 amountToPay,
    uint256 amountOfDebt,
    DataTypes.SignMarket calldata signMarket,
    DataTypes.EIP712Signature calldata sig
 ) external
```

It allows users to perform a buy-now operation on an order. It validates the signature, retrieves the order and loan details, validates the buy-now action, transfers the buy-now amount, creates a new loan for the buyer if a debt is requested, refunds any existing bid, and transfers the bought assets to the buyer.

### Parameters:

`claimOnUWallet`: A flag indicating whether to claim the assets on the user's Unlockd wallet.

`orderId`: The ID of the order to buy.

`amountToPay`: The amount to pay for the buy now operation.

`amountOfDebt`: The amount of debt associated with the buy-now operation.

`signMarket`: The signed market data.

`sig`: The EIP-712 signature for the buy now operation.

## Signature

#### `signMarket` (type: `DataTypes.SignMarket`), it contains the following fields:

`loan` (type: `DataTypes.SignLoanConfig`): The loan configuration data, including the loan ID, aggregated loan price, LTV, liquidation threshold, total assets, nonce, and deadline.

`assetId` (type: `bytes32`): The ID of the asset involved in the market action.

`collection` (type: `address`): The address of the asset collection.

`tokenId` (type: `uint256`): The token ID of the asset.

`assetPrice` (type: `uint256`): The price of the asset.

`assetLtv` (type: `uint256`): The loan-to-value ratio of the asset.

`nonce` (type: `uint256`): The nonce value is used to ensure the uniqueness of the signature and prevent replay attacks.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.

#### `sig` (type: `DataTypes.EIP712Signature`), it contains the following fields:

`v` (type: `uint8`): The recovery ID of the signature.

`r` (type: `bytes32`): The first 32 bytes of the signature.

`s` (type: `bytes32`): The second 32 bytes of the signature.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.


# Auction

`Auction.sol` is a module contract that handles auction-related functionalities in the Unlockd Protocol, such as placing bids, redeeming assets, and finalizing auctions.

### Key functions:

```solidity
function getAmountToReedem(
    bytes32 loanId,
    bytes32[] calldata assets
) public view returns (uint256, uint256, uint256)
```

Calculates the amount required to redeem assets from an auction, including the total amount, total debt amount, and total bidder bonus amount.

### Parameters:

`loanId`: The ID of the loan associated with the auction.

`assets`: An array of asset IDs to be redeemed.

### Returns:

The total amount required to redeem the assets.

The total debt amount.

The total bidder bonus amount.

***

```solidity
function getMinBidPriceAuction(
    bytes32 loanId,
    bytes32 assetId,
    uint256 assetPrice,
    uint256 aggLoanPrice,
    uint256 aggLtv
) external view returns (uint256 minBid)
```

Calculates the minimum bid price for an asset in an auction based on the loan details and asset information.

### Parameters:

`loanId`: The ID of the loan associated with the auction.

`assetId`: The ID of the asset.

`assetPrice`: The price of the asset.

`aggLoanPrice`: The aggregated loan price.

`aggLtv`: The aggregated loan-to-value ratio.

### Returns:

The minimum bid price for the asset.

***

```solidity
function getOrderAuction(
    bytes32 orderId
) external view returns (DataTypes.Order memory)
```

Retrieves the details of an auction order.

### Parameters:

`orderId`: The ID of the auction order.

### Returns:

The auction order details.

***

```solidity
function bid(
    uint128 amountToPay,
    uint128 amountOfDebt,
    DataTypes.SignAuction calldata signAuction,
    DataTypes.EIP712Signature calldata sig
) external 
```

Allows users to place a bid in an auction. It validates the signature, updates the loan state, transfers the bid amount, creates a new loan for the bidder if a debt is requested, and updates the auction order with the new bid details.

### Parameters:

`amountToPay`: The amount to pay for the bid.

`amountOfDebt`: The amount of debt associated with the bid.

`signAuction`: The signed auction data.

`sig`: The EIP-712 signature for the bid.

### Emits:&#x20;

`AuctionBid` event.

***

```solidity
function redeem(
    uint256 amount,
    bytes32[] calldata assets,
    DataTypes.SignAuction calldata signAuction,
    DataTypes.EIP712Signature calldata sig
) external
```

Allows the auction owner to redeem assets from an auction. It validates the signature, transfers the redemption amount, distributes the funds to the bidders, and updates the loan state.

### Parameters:

`amount`: The amount to pay for the redemption.

`assets`: An array of asset IDs to be redeemed.

`signAuction`: The signed auction data.

`sig`: The EIP-712 signature for the redemption.

### Emits:&#x20;

`AuctionRedeem` event.

***

```solidity
function finalize(
    bool claimOnUWallet,
    bytes32 orderId,
    DataTypes.Asset calldata asset,
    DataTypes.SignAuction calldata signAuction,
    DataTypes.EIP712Signature calldata sig
) external
```

It allows anyone to finalize an expired auction. It validates the signature, retrieves the auction order and loan details, transfers the auctioned asset to the winning bidder, distributes the funds to the auction owner, and updates the loan state.

### Parameters:

`claimOnUWallet`: A flag indicating whether to claim the assets on the user's Unlockd wallet.

`orderId`: The ID of the auction order.

`asset`: The asset being auctioned.

`signAuction`: The signed auction data.

`sig`: The EIP-712 signature for the finalization.

### Emits:&#x20;

`AuctionFinalize` event.

## Signature

#### `signAuction` (type: `DataTypes.SignAuction`), it contains the following fields:

`loan` (type: `DataTypes.SignLoanConfig`): The loan configuration data, including the loan ID, aggregated loan price, LTV, liquidation threshold, total assets, nonce, and deadline.

`assets` (type: `bytes32[]`): An array of asset IDs involved in the auction.

`assetPrice` (type: `uint256`): The price of the asset being auctioned.

`assetLtv` (type: `uint256`): The loan-to-value ratio of the asset being auctioned.

`endTime` (type: `uint40`): The end time of the auction.

`nonce` (type: `uint256`): The nonce value is used to ensure the uniqueness of the signature and prevent replay attacks.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.

#### `sig` (type: `DataTypes.EIP712Signature`), it contains the following fields:

`v` (type: `uint8`): The recovery ID of the signature.

`r` (type: `bytes32`): The first 32 bytes of the signature.

`s` (type: `bytes32`): The second 32 bytes of the signature.

`deadline` (type: `uint256`): The deadline timestamp until which the signature is considered valid.


# UTokenVault

`UTokenVault.sol` is a core contract that manages the reserves and handles deposits, withdrawals, borrowing, and repaying of assets within the Unlockd Protocol.

### Key functions:

```solidity
function createMarket(
    IUTokenVault.CreateMarketParams calldata params
) external onlyAdmin 
```

Creates a new market for a specific underlying asset.

### Parameters:

`params`: The parameters for creating the market.

***

```solidity
function deposit(
    address underlyingAsset, 
    uint256 amount, 
    address onBehalfOf
) external
```

Deposits assets into the specified market.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`amount`: The amount to deposit.

`onBehalfOf`: The address of the user to deposit on behalf of.

***

```solidity
function withdraw(
    address underlyingAsset, 
    uint256 amount, 
    address to
) external
```

Withdraws assets from the specified market.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`amount`: The amount to withdraw.

`to`: The address to withdraw the assets to.

***

```solidity
function borrow(
    address underlyingAsset,
    bytes32 loanId,
    uint256 amount,
    address to,
    address onBehalfOf
) external onlyProtocol
```

Borrows assets from the specified market.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`loanId`: The ID of the loan associated with the borrow.

`amount`: The amount to borrow.

`to`: The address to transfer the borrowed assets to.

`onBehalfOf`: The address of the user borrowing on behalf of.

***

```solidity
function repay(
    address underlyingAsset,
    bytes32 loanId,
    uint256 amount,
    address from,
    address onBehalfOf
) external onlyProtocol
```

Repays a borrowed amount to the specified market.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`loanId`: The ID of the loan to repay.

`amount`: The amount to repay.

`from`: The address to transfer the repayment from.

`onBehalfOf`: The address of the user repaying on behalf of.

***

```solidity
function updateState(address underlyingAsset) external
```

This function updates the state of a reserve for a given underlying asset. It calculates the current liquidity and variable borrow rates based on the reserve's configuration and the market's supply and borrow balances. It also updates the reserve's indexes and performs any necessary actions based on the reserve's strategy.

### Parameters:

`underlyingAsset`: The address of the underlying asset to update the state for.

***

```solidity
function setActive(
    address underlyingAsset, 
    bool isActive
) external onlyEmergencyAdmin
```

This function allows an emergency admin to set the active state of a reserve for a given underlying asset. When a reserve is active, it allows deposits, withdrawals, borrowing, and repaying. When it is inactive, these actions are disabled.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`isActive`: A boolean indicating whether to set the reserve as active or not.

***

```solidity
function setFrozen(
    address underlyingAsset, 
    bool isFrozen
) external onlyEmergencyAdmin 
```

This function allows an emergency admin to set the frozen state of a reserve for a given underlying asset. When a reserve is frozen, it disables deposits, withdrawals, borrowing, and repaying, effectively halting all actions related to that reserve.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`isFrozen`: A boolean indicating whether to set the reserve as frozen or not.

***

```solidity
function setPaused(
    address underlyingAsset, 
    bool isPaused
) external onlyEmergencyAdmin
```

This function allows an emergency admin to set the paused state of a reserve for a given underlying asset. When a reserve is paused, it temporarily disables deposits, withdrawals, borrowing, and repaying, similar to the frozen state. However, the paused state is typically used for temporary maintenance or upgrades.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`isPaused`: A boolean indicating whether to set the reserve as paused or not.

***

```solidity
function setCaps(
    address underlyingAsset,
    uint256 minCap,
    uint256 depositCap,
    uint256 borrowCap
) external onlyEmergencyAdmin 
```

This function allows an emergency admin to set the caps for a reserve. The caps include the minimum cap, deposit cap, and borrow cap. These caps are used to limit the maximum amounts that can be deposited or borrowed from the reserve, helping to manage risk and maintain stability.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`minCap`: The minimum cap for the reserve.

`depositCap`: The deposit cap for the reserve.

`borrowCap`: The borrow cap for the reserve.

***

```solidity
function disableStrategy(
    address underlyingAsset
) external onlyEmergencyAdmin
```

This function allows an emergency admin to disable the strategy associated with a reserve. When a strategy is disabled, the reserve will no longer invest or withdraw funds from the strategy, and all assets will remain in the reserve.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

***

```solidity
function updateReserveStrategy(
    address underlyingAsset,
    address newStrategy
) external onlyEmergencyAdmin 
```

This function allows an emergency admin to update the strategy associated with a reserve. It replaces the current strategy with a new one, allowing for dynamic changes to the investment strategy used by the reserve.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`newStrategy`: The address of the new strategy for the reserve.

***

```solidity
function validateReserveType(
    Constants.ReserveType currentReserveType,
    Constants.ReserveType reserveType
) external pure returns (bool) 
```

This function validates the compatibility of reserve types. It checks if the given reserve type is compatible with the current reserve type of a reserve. This is used to ensure that only compatible reserve types are allowed when updating or creating reserves

### Parameters:

`currentReserveType`: The current reserve type.

`reserveType`: The reserve type to validate against.

### Returns:&#x20;

A boolean indicates whether the reserve types are compatible.

***

```solidity
function getReserveData(
    address underlyingAsset
  ) external view returns (DataTypes.ReserveData memory) 
```

This function retrieves the reserve data for a given underlying asset. It returns a struct containing various information about the reserve, such as the liquidity index, variable borrow index, current rates, and configuration settings.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

### Returns:&#x20;

The reserve data for the given underlying asset.

***

```solidity
function getScaledToken(
    address underlyingAsset
) external view returns (address)
```

This function retrieves the address of the scaled token associated with a given underlying asset. The scaled token represents the share of the underlying asset held by users in the reserve.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

### Returns:&#x20;

The address of the scaled token for the given underlying asset.

***

```solidity
function getScaledTotalDebtMarket(
    address underlyingAsset
) external view returns (uint256)
```

This function retrieves the total scaled debt for a market associated with a given underlying asset. The scaled debt represents the total borrowing in the market, adjusted by the variable borrow index.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

### Returns:&#x20;

The total scaled debt for the market.

***

```solidity
function getTotalDebtFromUser(
    address underlyingAsset,
    address user
) external view returns (uint256)
```

This function retrieves the total debt of a user in a market associated with a given underlying asset. It represents the user's total borrowing amount in the market.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`user`: The address of the user.

### Returns:&#x20;

The total debt of the user in the market.

***

```solidity
function getScaledTotalDebtFromUser(
    address underlyingAsset,
    address user
) external view returns (uint256)
```

This function retrieves the total scaled debt of a user in a market associated with a given underlying asset. The scaled debt represents the user's total borrowing amount, adjusted by the variable borrow index.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`user`: The address of the user.

### Returns:&#x20;

The total scaled debt of the user in the market.

***

```solidity
function getDebtFromLoanId(
    address underlyingAsset,
    bytes32 loanId
) external view returns (uint256) 
```

This function retrieves the debt associated with a specific loan ID in a market for a given underlying asset. It represents the borrowing amount tied to a particular loan.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`loanId`: The ID of the loan.

### Returns:&#x20;

The debt associated with the loan ID in the market.

***

```solidity
function getScaledDebtFromLoanId(
    address underlyingAsset,
    bytes32 loanId
) external view returns (uint256)
```

This function retrieves the scaled debt associated with a specific loan ID in a market for a given underlying asset. The scaled debt represents the borrowing amount tied to a particular loan, adjusted by the variable borrow index.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`loanId`: The ID of the loan.

### Returns:&#x20;

The scaled debt associated with the loan ID in the market.

***

```solidity
function getBalances(
    address underlyingAsset
) external view returns (DataTypes.MarketBalance memory) 
```

This function retrieves the balances for a given underlying asset in a market. It returns a struct containing information such as the total supply, total borrow, and last update timestamp.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

### Returns:&#x20;

The balances for the given underlying asset.

***

```solidity
function getBalanceByUser(
    address underlyingAsset, 
    address user
) external view returns (uint256) 
```

This function retrieves the balance of a user in a market for a given underlying asset. It represents the user's supply balance in the market.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`user`: The address of the user.

### Returns:&#x20;

The balance of the user in the market.

***

```solidity
function getScaledBalanceByUser(
    address underlyingAsset,
    address user
) external view returns (uint256) 
```

This function retrieves the scaled balance of a user in a market for a given underlying asset. The scaled balance represents the user's supply balance, adjusted by the liquidity index.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

`user`: The address of the user.

### Returns:&#x20;

The scaled balance of the user in the market.

***

```solidity
function totalSupply(
    address underlyingAsset
) external view returns (uint256)
```

This function retrieves the total supply of a market for a given underlying asset. It represents the total amount of the underlying asset supplied by users to the market.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

### Returns:&#x20;

The total supply of the market.

***

```solidity
function totalAvailableSupply(
    address underlyingAsset
) external view returns (uint256) 
```

This function retrieves the total available supply of a market for a given underlying asset. It represents the total amount of the underlying asset that is available for borrowing or withdrawal, taking into account any assets invested in strategies.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

### Returns:&#x20;

The total available supply of the market.

***

```solidity
function totalSupplyNotInvested(
    address underlyingAsset
) external view returns (uint256) 
```

This function retrieves the total supply not invested in strategies for a market associated with a given underlying asset. It represents the portion of the total supply that is not currently invested and is available for immediate use.

### Parameters:

`underlyingAsset`: The address of the underlying asset.

### Returns:&#x20;

The total supply not invested in the market.


# BaseToken

`BaseToken.sol` is a contract that provides the base implementation for ERC20 tokens used within the Unlockd Protocol.

### Key functions:

<pre class="language-solidity"><code class="lang-solidity"><strong>function __BaseToken_init(
</strong>    address aclManager_, 
    address uTokenVault_, 
    uint8 decimals_, 
    string calldata name_, 
    string calldata symbol_
) internal onlyInitializing
</code></pre>

Initializes the `BaseToken` contract with the provided parameters.

### Parameters:

`aclManager_`: The address of the ACL manager contract.

`uTokenVault_`: The address of the UToken vault contract.

`decimals_`: The number of decimals used by the token.

`name_`: The name of the token.

`symbol_`: The symbol of the token.

***

```solidity
function setActive(bool active) external onlyEmergencyAdmin
```

Sets the active state of the token.

### Parameters:

`active`: A boolean indicating whether to set the token as active or not.

***

```solidity
function setFrozen(bool frozen) external onlyEmergencyAdmin
```

Sets the frozen state of the token.

### Parameters:

`frozen`: A boolean indicating whether to set the token as frozen or not.

***

```solidity
function decimals() public view virtual override returns (uint8)
```

Returns the number of decimals used by the token.

### Returns:&#x20;

The number of decimals as a `uint8`.

***

```solidity
function _transfer(
    address sender, 
    address recipient, 
    uint256 amount
) internal virtual override
```

Transfers tokens from the sender to the recipient.

### Parameters:

`sender`: The address of the sender.

`recipient`: The address of the recipient.

`amount`: The amount of tokens to transfer.

***

```solidity
function _mint(
    address account, 
    uint256 amount
) internal virtual override isFrozen isActive
```

Mints new tokens to the specified account.

### Parameters:

`account`: The address of the account to mint tokens to.

`amount`: The amount of tokens to mint.

***

<pre class="language-solidity"><code class="lang-solidity"><strong>function _burn(
</strong>    address account, 
    uint256 amount
) internal virtual override isFrozen
</code></pre>

Burns tokens from the specified account.

### Parameters:

`account`: The address of the account to burn tokens from.

`amount`: The amount of tokens to burn.


# ScaledToken

`ScaledToken.sol` is a contract that implements the scaled token mechanism used within the Unlockd Protocol. Scaled tokens represent a user's share of the underlying assets in a reserve, and their balances are adjusted based on the reserve's interest rates and liquidity index.

### Key functions:

```solidity
function mint(
    address user,
    uint256 amount,
    uint256 index
) external onlyUTokenVault returns (uint256)
```

Mints new scaled tokens to a specified address.

### Parameters:

`account`: The address to mint tokens to.

`amount`: The amount of tokens to mint.

`liquidityIndex`: The liquidity index at the time of minting.

***

```solidity
function burn(
    address user,
    uint256 amount,
    uint256 index
  ) external onlyUTokenVault returns (uint256)
```

Burns scaled tokens from a specified address.

### Parameters:

`account`: The address to burn tokens from.

`amount`: The amount of tokens to burn.

`liquidityIndex`: The liquidity index at the time of burning.

### Returns:&#x20;

The actual amount of tokens burned.

***


# WethGateway

`WETHGateway.sol` is a contract that serves as a gateway for wrapping and unwrapping ETH and interacting with WETH (Wrapped ETH) within the Unlockd Protocol.

### Key functions:

<pre class="language-solidity"><code class="lang-solidity"><strong>function authorizeProtocol(
</strong>    address uTokenVault
) external onlyOwner
</code></pre>

Authorizes the Unlockd Protocol to interact with the WETH contract.

Parameters:

`uTokenVault`: The address of the UTokenVault contract.

***

```solidity
function depositETH(address onBehalfOf) external payable override
```

Deposits ETH and mints corresponding WETH tokens.

### Parameters:

`onBehalfOf`: The address to deposit ETH on behalf of.

***

```solidity
function withdrawETH(uint256 amount, address to) external override
```

Withdraws WETH tokens and receives ETH.

### Parameters:

`amount`: The amount of WETH to withdraw.

`to`: The address to receive the withdrawn ETH.

***

```solidity
function emergencyTokenTransfer(
    address token, 
    address to, 
    uint256 amount
) external onlyOwner
```

Performs an emergency transfer of ERC20 tokens.

### Parameters:

`token`: The address of the token to transfer.

`to`: The recipient address of the token transfer.

`amount`: The amount of tokens to transfer.

***

```solidity
function emergencyEtherTransfer(
    address to, 
    uint256 amount
) external onlyOwner
```

Performs an emergency transfer of ETH.

### Parameters:

`to`: The recipient address of the ETH transfer.

`amount`: The amount of ETH to transfer.

***

<pre class="language-solidity"><code class="lang-solidity"><strong>function getWETHAddress() external view returns (address)
</strong></code></pre>

Returns the address of the WETH contract.


# ReservoirAdapter

`ReservoirAdapter.sol` is an adapter contract that enables the Unlockd Protocol to interact with the Reservoir marketplace. It implements the IMarketAdapter interface and provides functions for selling, buying, and canceling orders on the Reservoir marketplace.

### Key functions:

```solidity
function preSell(
    PreSellParams memory params
) public payable onlyProtocol
```

Prepares an asset for selling on the Reservoir marketplace.

### Parameters:

`params`: The parameters for preparing the sell operation.

***

```solidity
function sell(
    SellParams memory params
) public payable onlyProtocol
```

Sells an asset on the Reservoir marketplace.

### Parameters:

`params`: The parameters for the sell operation.

***

```solidity
function preBuy(
    PreBuyParams memory params
) public payable onlyProtocol
```

Prepares for buying an asset on the Reservoir marketplace.

### Parameters:

`params`: The parameters for preparing the buy operation.

***

```solidity
function buy(
    BuyParams memory params
) public payable onlyProtocol returns (uint256)
```

Buys an asset on the Reservoir marketplace.

### Parameters:

`params`: The parameters for the buy operation.

Returns: The actual cost of the buy operation.


# MaxApyStrategy

`MaxApyStrategy.sol` is a contract that defines a strategy for managing funds and interacting with the MaxApy Vault within the Unlockd Protocol. It implements the IStrategy interface and provides functions for supplying funds to the MaxApy Vault, withdrawing funds from the vault, and calculating the optimal investment amount based on the strategy's configuration.

### Key functions:

```solidity
function asset() external view returns (address)
```

Returns the address of the underlying asset managed by the strategy.

***

```solidity
function getConfig() 
external view returns (StrategyConfig memory)
```

Returns the configuration of the MaxApy strategy.

***

```solidity
function balanceOf(address owner) 
external view returns (uint256)
```

Returns the balance of the specified owner in the MaxApy Vault.

### Parameters:

`owner`: The address of the owner.

***

```solidity
function calculateAmountToSupply(
    uint256 totalSupplyNotInvested, 
    address from_, 
    uint256 amount_
) external view returns (uint256)
```

Calculates the amount to supply to the MaxApy Vault based on the current state.

### Parameters:

`totalSupplyNotInvested`: The total supply not invested in the vault.

`from_`: The address supplying the funds.

`amount_`: The amount being supplied.

### Returns:&#x20;

The amount to supply to the MaxApy Vault.

***

```solidity
function supply(
    address vault_, 
    address asset_, 
    address from_, 
    uint256 amount_
) external returns (uint256)
```

Supplies funds to the MaxApy Vault.

### Parameters:

`vault_`: The address of the MaxApy Vault.

`asset_`: The address of the asset being supplied.

`from_`: The address supplying the funds.

`amount_`: The amount being supplied.

### Returns:&#x20;

The actual amount supplied to the vault.

***

```solidity
function calculateAmountToWithdraw(
    uint256 totalSupplyNotInvested_, 
    address from_, 
    uint256 amount_
) external view returns (uint256)
```

Calculates the amount to withdraw from the MaxApy Vault based on the current state.

### Parameters:

`totalSupplyNotInvested_`: The total supply not invested in the vault.

`from_`: The address withdrawing the funds.

`amount_`: The amount being withdrawn.

### Returns:&#x20;

The amount to withdraw from the MaxApy Vault.

***

```solidity
function withdraw(
    address vault_, 
    address to_, 
    uint256 amount_
) external returns (uint256)
```

Withdraws funds from the MaxApy Vault.

### Parameters:

`vault_`: The address of the MaxApy Vault.

`to_`: The address to receive the withdrawn funds.

`amount_`: The amount being withdrawn.

### Returns:&#x20;

The actual amount withdrawn from the vault.

***

<pre class="language-solidity"><code class="lang-solidity"><strong>function updateDeepConfig(
</strong><strong>    uint256 minAmountToInvest_, 
</strong><strong>    uint256 ratio_
</strong><strong>) external onlyAdmin
</strong></code></pre>

Updates the deep configuration of the strategy.

Parameters:

`minAmountToInvest_`: The minimum amount to invest in the MaxApy Vault.

`ratio_`: The ratio used for calculating the amount to withdraw.

Only callable by the admin role.

***

```solidity
function updateStrategyConfig(
    uint256 minCap_, 
    uint256 percentageToInvest_
) external onlyAdmin
```

Updates the strategy configuration.

### Parameters:

`minCap_`: The minimum cap for the strategy.

`percentageToInvest_`: The percentage of funds to invest in the MaxApy Vault.

Only callable by the admin role.


# CoreStorage

The `CoreStorage.sol` contract is responsible for storing the core storage variables and mappings used by the Unlockd Protocol.

### Key storage variables:

`_moduleLookup`: Mapping of module IDs to their implementation addresses.

`_proxyLookup`: Mapping of module IDs to their proxy addresses (only for single-proxy modules).

`_trustedSenders`: Mapping of proxy addresses to their trusted sender information.

`_aclManager`: Address of the ACL (Access Control List) manager contract.

`_walletRegistry`: Address of the wallet registry contract.

`_allowedControllers`: Address of the allowed controllers contract.

`_reserveOracle`: Address of the reserve oracle contract.

`_signer`: Address of the signer used for signature verification.

`_uTokenVault`: Address of the UToken vault contract.

`_safeERC721`: Address of the SafeERC721 contract.

`_signNonce`: Mapping of addresses to their current signature nonce.

`_allowedCollections`: Mapping of collection addresses to their allowed reserve types.

`_allowedMarketAdapter`: Mapping of market adapter addresses to their active status.

`_loans`: Mapping of loan IDs to their corresponding loan data.

`_orders`: Mapping of order IDs to their corresponding order data.


# UVaultStorage

The `UVaultStorage.sol` contract is responsible for storing the storage variables and mappings specific to the UToken vault.

### Key storage variables:

`_sharesTokenImp`: Address of the shares token implementation contract.

`reserves`: Mapping of underlying asset addresses to their reserve data.

`balances`: Mapping of underlying asset addresses to their market balance data.

`borrowScaledBalanceByLoanId`: Mapping of underlying asset addresses and loan IDs to the scaled borrow balance.

`borrowScaledBalanceByUser`: Mapping of underlying asset addresses and user addresses to the scaled borrow balance.


# Ethereum Sepolia

The address deployed.

<table><thead><tr><th width="272.3333333333333">Contracts</th><th>Ethereum</th></tr></thead><tbody><tr><td>ACLManager</td><td>0x381904881c1e8ac2551b654e5cf4e66a1923a7d1</td></tr><tr><td>Unlockd</td><td>0x04378c71396103a178e462032d5e6fa396ad9247</td></tr><tr><td>UTokenVault</td><td>0x4fa024dbeb2de64d4fd4f1692996979aead0cd93</td></tr><tr><td>ReservoirAdapter</td><td>0xde49bc894edc1907f1be47cedcbca2d65d6c11f9</td></tr><tr><td>WETHGateway</td><td>0x5add60db21014b44af8f6c667e9ad810ece0760b</td></tr><tr><td>MaxApyStrategy</td><td>0xc259e737bbf37511f9c82e5580d5a7ed233c7730</td></tr><tr><td>Action</td><td>0x269605dd60b609a49297e4be6a9e76189bb536cd</td></tr><tr><td>Auction</td><td>0xf08cc6ae6fa73ddd152aed38f44e6b40d8afe53e</td></tr><tr><td>BuyNow</td><td>0xbc07ee6899db7389b7dee5779ccdf8d9908579c3</td></tr><tr><td>SellNow</td><td>0x21a74ff38e167f921a3565c3698ed8f9af65af65</td></tr><tr><td>Market</td><td>0x32d7cf863e0d578f76efff1a41cf4a4a4759259d</td></tr></tbody></table>


# Ethereum Mainnet

The address deployed.

<table><thead><tr><th width="272.3333333333333">Contracts</th><th>Ethereum</th></tr></thead><tbody><tr><td>ACLManager</td><td>0x7710ac75c8738345707a4289b80b1912b8bb98ea</td></tr><tr><td>Unlockd</td><td>0xcd16ad66f4786a9224f53af13987fc2ed6fde0cb</td></tr><tr><td>UTokenVault</td><td>0x25299e9Ec27c242465587B8A2Aa70bcE02636cDA</td></tr><tr><td>ReservoirAdapter</td><td>0x2038e2983fd88a9f23962fcb86cbdacef3d9f5e7</td></tr><tr><td>Action</td><td>0xbfd43899be1f0c8e011f289a7fac4ba7a196cfef</td></tr><tr><td>Auction</td><td>0x56bbfbfb7e793c7bf8378388686dedd6caa19f7f</td></tr><tr><td>BuyNow</td><td>0x27b42656d0be9e80495ba52ec4574c4d6645e64d</td></tr><tr><td>SellNow</td><td>0xc376532cba755388d89abadb192a1da4cfb2eddd</td></tr><tr><td>Market</td><td>0x23262564b9af9e330ae9bbddcc00c06d6e49f9f0</td></tr></tbody></table>

## Catapulta links:

| Unlockd     | <https://catapulta.sh/report/badb6771-3e10-477e-9277-61cad52da93d> |
| ----------- | ------------------------------------------------------------------ |
| Modules     | <https://catapulta.sh/report/f09be5b3-2744-4486-bff9-9b37a9078de7> |
| UTokenVault | <https://catapulta.sh/report/e6c8afaf-b531-4141-a5be-46ea8c3bc117> |
| Wallet      | <https://catapulta.sh/report/324d998b-aebb-4b6b-b98d-3ae254a0900f> |
| ACLManager  | <https://catapulta.sh/report/22c1caaf-8572-41f5-8316-43f06c7e1b7d> |


# Introduction

Welcome to the Unlockd Wallet developer documentation. This documentation aims to comprehensively understand the smart contracts and architecture behind the Unlockd Wallet, a cutting-edge solution for secure asset management and delegation on the blockchain.

The Unlockd Wallet is built upon the Gnosis Safe framework and extends its functionality to enable granular asset and signature delegation. It empowers asset owners to delegate specific assets to trusted parties for a defined duration while maintaining ultimate control and ownership. The wallet also supports signature delegation, allowing delegates to sign transactions on behalf of the asset owner within predefined limits.

The Unlockd Wallet ecosystem comprises several smart contracts that provide a secure and flexible delegation mechanism. The main components include:

1. DelegationWalletFactory: Responsible for deploying and configuring new Delegation Wallets.
2. DelegationWalletRegistry: Keeps track of deployed Delegation Wallets and their associated components.
3. GnosisSafe: The underlying Gnosis Safe contract is the foundation for the Delegation Wallet.
4. DelegationOwner: Manages asset and signature delegation, interacting with DelegationRecipes and AllowedControllers.
5. GuardOwner: Manages the TransactionGuard contract, which enforces delegation and locking rules.
6. ProtocolOwner: Handles protocol-level functions and permissions.
7. TransactionGuard: Enforces delegation and locking rules, validating transactions based on predefined conditions.
8. DelegationRecipes: Registers and manages allowed functions for specific asset collections.
9. AllowedControllers: Manages allowed delegation and lock controllers.

These contracts enable asset owners to grant specific permissions to delegates while maintaining control over their assets.

Documentation Overview This documentation is structured to provide a deep dive into the Unlockd Wallet's architecture, smart contracts, and interactions. It is intended for developers, auditors, and anyone interested in understanding its inner workings.

The following sections will cover:

1. Architecture: A high-level overview of the Unlockd Wallet's contract interactions and data flow.
2. Smart Contracts: This section provides detailed explanations of each smart contract, including its purpose, state variables, functions, and events.

By exploring this documentation, you will comprehensively understand the Unlocked Wallet's underlying technology and how it achieves secure and flexible asset delegation.


# Architecture

The Unlockd Wallet's architecture is designed to provide a secure and flexible framework for asset and signature delegation. It leverages the Gnosis Safe contracts as the foundation and extends their functionality. Let's explore the architecture in detail.

The following diagram illustrates the main contract interactions within the Unlockd Wallet ecosystem:

<figure><img src="https://1802212726-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeqGi7JVGKRiZ8CDr4vSm%2Fuploads%2FtCL6t0YXkLgkHWB40UVT%2Fimage.png?alt=media&amp;token=3e632071-14aa-4de5-aeca-ab352ba449be" alt=""><figcaption></figcaption></figure>

#### DelegationWalletFactory:

* Deploys new instances of the Delegation Wallet components (GnosisSafe, DelegationOwner, GuardOwner, ProtocolOwner, TransactionGuard).
* Registers the deployed wallet components in the DelegationWalletRegistry.

***

#### DelegationWalletRegistry:

* Keeps track of all deployed Delegation Wallets and their associated components.
* It provides functions to retrieve wallet information and component addresses.

***

#### GnosisSafe:

* The core contract that holds assets and executes transactions.
* Integrated with the Unlockd Wallet's delegation mechanisms.

***

#### DelegationOwner:

* Manages asset and signature delegation.
* Interacts with the TransactionGuard to enforce delegation rules.
* Utilizes DelegationRecipes to determine allowed functions for asset collections.
* Integrates with AllowedControllers to manage delegation and lock controllers.

***

#### GuardOwner:

* Manages the setup and initialization of the TransactionGuard contract.
* Deploys a new instance of the TransactionGuard contract using a beacon proxy.
* Sets the TransactionGuard as the guard for the GnosisSafe contract.
* Interacts with the TransactionGuard to perform guard-related operations.

***

#### ProtocolOwner:

* Handles protocol-level functions and permissions.
* Interacts with the TransactionGuard and DelegationOwner contracts.

***

#### TransactionGuard:

* Enforces delegation and locking rules on transactions.
* Validates transactions based on predefined conditions and allowances.
* Interacts with the DelegationOwner, GuardOwner, and ProtocolOwner contracts.

***

#### DelegationRecipes:

* Registers and manages allowed functions for specific asset collections.
* Defines the rules and permissions for asset delegation.

***

#### AllowedControllers:

* Manages the allowed delegation and lock controllers.
* Determines which addresses are authorized to perform delegation and locking operations.

***

## The Unlockd Wallet's architecture facilitates the following data flow:

#### Deployment:

* The DelegationWalletFactory deploys new instances of the Delegation Wallet components.
* The deployed components are registered in the DelegationWalletRegistry.

***

#### Asset Delegation:

* The DelegationOwner contract manages asset delegation.
* It interacts with the TransactionGuard to enforce delegation rules.
* The DelegationRecipes contract defines the allowed functions for asset collections.

***

#### Signature Delegation:

* The DelegationOwner contract also manages signature delegation.
* It validates signatures against the delegated signing authority.

***

#### Transaction Execution:

* Transactions are initiated through the GnosisSafe contract.
* The TransactionGuard intercepts and validates transactions based on delegation and locking rules.
* The DelegationOwner, GuardOwner, and ProtocolOwner contracts interact with the TransactionGuard to enforce specific rules and permissions.

***

#### Access Control:

* The AllowedControllers contract manages the allowed delegation and lock controllers.
* It determines which addresses are authorized to perform delegation and locking operations.


# DelegationWalletFactory

The DelegationWalletFactory contract is responsible for deploying and configuring new instances of the Delegation Wallet components. It acts as the entry point for creating a new wallet and ensures all necessary contracts are correctly initialized.&#x20;

## Key Functions:

```solidity
function deploy(address _delegationController) 
external 
returns (
    address, 
    address, 
    address, 
    address
)
```

Deploys a new Delegation Wallet with the `msg.sender` as the owner.

### Parameters:

`_delegationController` (address): The address of the delegation controller.

### Returns:

The addresses of the deployed GnosisSafe, DelegationOwner, ProtocolOwner, and GuardOwner contracts.

***

```solidity
function deployFor(address _owner, address _delegationController) 
public 
returns (
    address, 
    address, 
    address, 
    address
    )
```

Deploys a new Delegation Wallet for a specified owner.

### Parameters:

`_owner` (address): The address of the wallet owner.

`_delegationController` (address): The address of the delegation controller.

### Returns:

The addresses of the deployed GnosisSafe, DelegationOwner, ProtocolOwner, and GuardOwner contracts.

***

## Interactions:

* Interacts with the GnosisSafeProxyFactory to deploy a new GnosisSafe contract.
* Interacts with the beacon proxies to deploy new instances of the GuardOwner, DelegationOwner, and ProtocolOwner contracts.
* Registers the deployed wallet components in the DelegationWalletRegistry.


# DelegationWalletRegistry

The DelegationWalletRegistry contract keeps track of all the deployed Delegation Wallets and their associated components. It provides a way to retrieve information about a specific wallet, such as its address and the addresses of its components.&#x20;

## Key Functions:

```solidity
function setFactory(address _delegationWalletFactory) external
```

Sets the address of the DelegationWalletFactory contract.

### Parameters:

`_delegationWalletFactory` (address): The address of the DelegationWalletFactory contract.

***

```solidity
function setWallet(
    address _wallet, 
    address _owner, 
    address _guard, 
    address _guardOwner, 
    address _delegationOwner, 
    address _protocolOwner
) external
```

Registers a new Delegation Wallet and its components in the registry.

### Parameters:

`_wallet` (address): The address of the GnosisSafe contract.

`_owner` (address): The address of the wallet owner.

`_guard` (address): The address of the TransactionGuard contract.

`_guardOwner` (address): The address of the GuardOwner contract.

`_delegationOwner` (address): The address of the DelegationOwner contract.

`_protocolOwner` (address): The address of the ProtocolOwner contract.

***

```solidity
function getWallet(address _wallet) 
external 
view 
returns (IDelegationWalletRegistry.Wallet memory)
```

Retrieves the information of a specific Delegation Wallet.

### Parameters:

`_wallet` (address): The address of the GnosisSafe contract.

### Returns:

The Wallet struct containing the addresses of the wallet components.

***

```solidity
function getOwnerWalletAddresses(
    address _owner
) external view returns (address[] memory);
```

Returns the entire set of wallet addresses for a given owner.

### Parameters:

`_owner` (address): The address of the wallet owner.&#x20;

### Returns:

An array of wallet addresses owned by the specified owner.

***

```solidity
function getOwnerWalletAt(
    address _owner, 
    uint256 _index
) 
external 
view 
returns (IDelegationWalletRegistry.Wallet memory);
```

Returns the wallet information at a specific index for a given owner.

### Parameters:

`_owner` (address): The address of the wallet owner.

`_index` (uint256): The index of the wallet in the owner's wallet set. &#x20;

### Returns:

The Wallet struct containing the addresses of the wallet components.

***

## Interactions:

* Receives wallet information from the DelegationWalletFactory during the deployment process.
* Provides functions for retrieving wallet information and component addresses.


# DelegationOwner

The DelegationOwner contract manages asset and signature delegation within the Unlockd Wallet. It allows the wallet owner to delegate specific assets to trusted parties for a defined duration and provides functionality for signature delegation.&#x20;

## Key Functions:

```solidity
function initialize(
    address _guard, 
    address _safe, 
    address _owner, 
    address _delegationController, 
    address _protocolOwner
) public
```

Initializes the DelegationOwner contract with the necessary parameters.

### Parameters:

`_guard` (address): The address of the TransactionGuard contract.

`_safe` (address): The address of the GnosisSafe contract.

`_owner` (address): The address of the wallet owner.

`_delegationController` (address): The address of the delegation controller.

`_protocolOwner` (address): The address of the protocol owner.

***

```solidity
function setDelegationController(
    address _delegationController, 
    bool _allowed
) external;
```

Sets a delegation controller address as allowed or disallowed.

### Parameters:

* `_delegationController` (address): The address of the delegation controller.
* `_allowed` (bool): Indicates whether the delegation controller is allowed or not.

***

<pre class="language-solidity"><code class="lang-solidity"><strong>function delegate(
</strong>    address _asset, 
    uint256 _id, 
    address _delegatee, 
    uint256 _duration
) external
</code></pre>

Delegates the usage of an asset to a delegatee for a specified duration.

### Parameters:

`_asset` (address): The address of the asset being delegated.

`_id` (uint256): The ID of the asset being delegated.

`_delegatee` (address): The address of the delegatee.

`_duration` (uint256): The duration of the delegation in seconds.

***

```solidity
function endDelegate(
    address _asset, 
    uint256 _id
) external;
```

&#x20;Ends the delegation of an asset.

### Parameters:

`_asset` (address): The address of the delegated asset.

`_id` (uint256): The ID of the delegated asset.

***

```solidity
function forceEndDelegation(
    address _asset, 
    uint256 _id
) external;
```

Forcefully ends the delegation of an asset by the protocol owner.

### Parameters:

`_asset` (address): The address of the delegated asset.

`_id` (uint256): The ID of the delegated asset.

***

```solidity
function delegateSignature(
    address[] calldata _assets, 
    uint256[] calldata _ids, 
    address _delegatee, 
    uint256 _duration
) external;
```

Delegates the usage of the signature to a delegatee for a specified duration, locking a group of assets.

### Parameters:

`_assets` (address\[]): An array of asset addresses being delegated.

`_ids` (uint256\[]): An array of asset IDs being delegated.

`_delegatee` (address): The address of the delegatee.

`_duration` (uint256): The duration of the signature delegation, expressed in seconds.

***

```solidity
function endDelegateSignature() external;
```

Ends the delegation of the signature, unlocking a group of assets.

***

```solidity
function execTransaction(
    address _asset, 
    uint256 _id, 
    address _to, 
    uint256 _value, 
    bytes calldata _data, 
    uint256 _safeTxGas, 
    uint256 _baseGas, 
    uint256 _gasPrice, 
    address _gasToken, 
    address payable _refundReceiver
) external returns (bool success)
```

Executes a transaction through the GnosisSafe wallet, validating the delegatee and allowed functions.

### Parameters:

`_asset` (address): The address of the delegated asset.

`_id` (uint256): The ID of the delegated asset.

`_to` (address): The destination address of the transaction.

`_value` (uint256): The amount of ETH to be sent with the transaction.

`_data` (bytes): The data payload of the transaction.

`_safeTxGas` (uint256): The gas limit for the transaction.

`_baseGas` (uint256): The base gas cost.

`_gasPrice` (uint256): The gas price used for the transaction.

`_gasToken` (address): The address of the token used for gas payment (0 for ETH).

`_refundReceiver` (address payable): The address that receives the gas payment refund.

### Returns:

A boolean indicating the success of the transaction execution.

***

```solidity
function isValidSignature(
    bytes memory _data, 
    bytes memory _signature
) public view override returns (bytes4);
```

Validates if a signature is valid based on the current signature delegation.

### Parameters:

`_data` (bytes): The hash of the signed data.

`_signature` (bytes): The signature bytes.&#x20;

### Returns:

The EIP1271 magic value if the signature is valid.

***

```solidity
function claimAsset(
    address _asset, 
    uint256 _id, 
    address _receiver
) external;
```

Sends an asset to a receiver if it is not delegated or locked.

### Parameters:

`_asset` (address): The address of the asset being claimed.

`_id` (uint256): The ID of the asset being claimed.

`_receiver` (address): The address of the receiver.

***

```solidity
function isAssetDelegated(
    address _asset, 
    uint256 _id
) external view returns (bool);
```

Returns if an asset is delegated or included in the current signature delegation.

### Parameters:

`_asset` (address): The address of the asset.

`_id` (uint256): The ID of the asset. Returns:

(bool): Indicates whether the asset is delegated or not.

***

```solidity
function isSignatureDelegated() 
external view returns (bool);
```

&#x20;Returns if the signature is delegated.

### Returns:

(bool): Indicates whether the signature is delegated or not.

***

```solidity
function isAllowedFunction(
    address _asset, 
    address _contract, 
    bytes4 _selector
) public view returns (bool);
```

Checks if a function is allowed to be executed by a delegatee of a given asset.

### Parameters:

`_asset` (address): The address of the delegated asset.

`_contract` (address): The address of the destination contract.

`_selector` (bytes4): The selector of the destination function.&#x20;

### Returns:

(bool): Indicates whether the function is allowed or not.

***

## Interactions:

* Interacts with the TransactionGuard contract to enforce delegation and locking rules.
* Utilizes the DelegationRecipes contract to determine allowed functions for asset collections.
* Integrates with the AllowedControllers contract to manage delegation and lock controllers.
* Executes transactions through the GnosisSafe contract.


# GuardOwner

The GuardOwner contract is responsible for deploying and initializing the TransactionGuard contract. It sets up the TransactionGuard as the guard for the GnosisSafe contract and manages guard-related operations.&#x20;

## Key Functions:

```solidity
function initialize(
    address _guardBeacon, 
    address _safe, 
    address _owner, 
    address _delegationOnwer, 
    address _protocolOwner
) public
```

Initializes the GuardOwner contract with the necessary parameters.

### Parameters:

`_guardBeacon` (address): The address of the TransactionGuard beacon contract.

`_safe` (address): The address of the GnosisSafe contract.

`_owner` (address): The address of the wallet owner.

`_delegationOnwer` (address): The address of the DelegationOwner contract.

`_protocolOwner` (address): The address of the ProtocolOwner contract.

***

```solidity
function _setupGuard(
    address _safe, 
    TransactionGuard _guard
) internal;
```

Internal function to set up the TransactionGuard as the guard for the GnosisSafe contract.

### Parameters:

`_safe` (address): The address of the GnosisSafe contract.

`_guard` (TransactionGuard): The address of the TransactionGuard contract.

***

## Interactions:

* Deploys a new instance of the TransactionGuard contract using a beacon proxy.
* Sets the TransactionGuard as the guard for the GnosisSafe contract.


# ProtocolOwner

The ProtocolOwner contract handles protocol-level functions and permissions within the Unlockd Wallet. It allows authorized protocol owners to execute specific actions and interacts with the TransactionGuard and DelegationOwner contracts.&#x20;

## Key Functions:

```solidity
function initialize(
    address _guard, 
    address _safe, 
    address _owner, 
    address _delegationOwner
) public
```

Initializes the ProtocolOwner contract with the necessary parameters.

### Parameters:

`_guard` (address): The address of the TransactionGuard contract.

`_safe` (address): The address of the GnosisSafe contract.

`_owner` (address): The address of the wallet owner.

`_delegationOwner` (address): The address of the DelegationOwner contract.

***

```solidity
function approveSale(
    address _collection, 
    uint256 _tokenId, 
    address _underlyingAsset, 
    uint256 _amount, 
    address _marketApproval, 
    bytes32 _loanId
) external;
```

Approves the sale of an asset and transfers the necessary approvals and permissions.

### Parameters:

`_collection` (address): The address of the asset collection.

`_tokenId` (uint256): The ID of the asset being sold.

`_underlyingAsset` (address): The address of the underlying asset.

`_amount` (uint256): The amount to be approved.

`_marketApproval` (address): The address of the market approval contract.

`_loanId` (bytes32): The ID of the loan associated with the sale.

***

```solidity
function execTransaction(
    address _to, 
    uint256 _value, 
    bytes calldata _data, 
    uint256 _safeTxGas, 
    uint256 _baseGas, 
    uint256 _gasPrice, 
    address _gasToken, 
    address payable _refundReceiver
) external returns (bool success)
```

Executes a transaction through the GnosisSafe wallet with protocol-level permissions.

### Parameters:

`_to` (address): The destination address of the transaction.

`_value` (uint256): The amount of ETH to be sent with the transaction.

`_data` (bytes): The data payload of the transaction.

`_safeTxGas` (uint256): The gas limit for the transaction.

`_baseGas` (uint256): The base gas cost.

`_gasPrice` (uint256): The gas price used for the transaction.

`_gasToken` (address): The address of the token used for gas payment (0 for ETH).

`_refundReceiver` (address payable): The address that receives the gas payment refund.

### Returns:

A boolean indicating the success of the transaction execution.

***

```solidity
function delegateOneExecution(
    address to, 
    bool value
) external;
```

Delegates the execution permission to a specified address for a single transaction.

### Parameters:

`to` (address): The address to delegate the execution permission to.

`value` (bool): Indicates whether to grant or revoke the execution permission.

***

```solidity
function isDelegatedExecution(
    address to
) external view returns (bool);
```

&#x20;Checks if an address has delegated execution permission.

### Parameters:

`to` (address): The address to check for delegated execution permission.&#x20;

### Returns:

(bool): Indicates whether the address has delegated execution permission or not.

***

```solidity
function isAssetLocked(
    bytes32 _id
) external view returns (bool);
```

Checks if an asset is locked.

### Parameters:

`_id` (bytes32): The ID of the asset.&#x20;

### Returns:

(bool): Indicates whether the asset is locked or not.

***

```solidity
function getLoanId(
    bytes32 index
) external view returns (bytes32);
```

Returns the loan ID assigned to a specific asset.

### Parameters:

`index` (bytes32): The index of the asset.&#x20;

### Returns:

(bytes32): The loan ID assigned to the asset.

***

```solidity
function setLoanId(
    bytes32 _index, 
    bytes32 _loanId
) external;
```

Sets the loan ID assigned to a specific asset.

### Parameters:

`_index` (bytes32): The index of the asset.

`_loanId` (bytes32): The loan ID to be assigned.

***

```solidity
function safeSetLoanId(
    address _asset, 
    uint256 _id, 
    bytes32 _loanId
) external;
```

Safely sets the loan ID assigned to a specific asset and resets approvals.

### Parameters:

`_asset` (address): The address of the asset.

`_id` (uint256): The ID of the asset.

`_loanId` (bytes32): The loan ID to be assigned.

***

```solidity
function changeOwner(
    address _asset, 
    uint256 _id, 
    address _newOwner
) external;
```

Changes the current ownership of an asset.

### Parameters:

`_asset` (address): The address of the asset.

`_id` (uint256): The ID of the asset.

`_newOwner` (address): The address of the new owner.

***

```solidity
function batchSetToZeroLoanId(
    bytes32[] calldata _assets
) external;
```

Batch function to set loan IDs to zero for a group of assets.

### Parameters:

`_assets` (bytes32\[]): An array of asset IDs.

***

```solidity
function batchSetLoanId(
    bytes32[] calldata _assets, 
    bytes32 _loanId
) external;
```

Batch function to set loan IDs to a specific value for a group of assets.

### Parameters:

`_assets` (bytes32\[]): An array of asset IDs.

`_loanId` (bytes32): The loan ID to be assigned.

***

## Interactions:

* Interacts with the TransactionGuard contract to enforce protocol-level rules and permissions.
* Interacts with the DelegationOwner contract to perform protocol-specific actions.


# TransactionGuard

The TransactionGuard contract enforces delegation and locking rules on transactions within the Unlockd Wallet. It validates transactions based on predefined conditions and allowances, ensuring that only authorized actions are executed.&#x20;

## Key Functions:

```solidity
function initialize(
    address _delegationOwner, 
    address _protocolOwner
) public
```

Initializes the TransactionGuard contract with the necessary parameters.

### Parameters:

`_delegationOwner` (address): The address of the DelegationOwner contract.

`_protocolOwner` (address): The address of the ProtocolOwner contract.

***

<pre class="language-solidity"><code class="lang-solidity"><strong>function checkTransaction(
</strong>    address _to, 
    uint256 _value, 
    bytes calldata _data, 
    Enum.Operation operation, 
    uint256 _safeTxGas, 
    uint256 _baseGas, 
    uint256 _gasPrice, 
    address _gasToken, 
    address payable _refundReceiver, 
    bytes memory _signatures, 
    address _msgSender
) external view
</code></pre>

Performs checks before executing a transaction, enforcing delegation and locking rules.

### Parameters:

`_to` (address): The destination address of the transaction.

`_value` (uint256): The amount of ETH to be sent with the transaction.

`_data` (bytes): The data payload of the transaction.

`operation` (Enum.Operation): The operation type (Call or DelegateCall).

`_safeTxGas` (uint256): The gas limit for the transaction.

`_baseGas` (uint256): The base gas cost.

`_gasPrice` (uint256): The gas price used for the transaction.

`_gasToken` (address): The address of the token used for gas payment (0 for ETH).

`_refundReceiver` (address payable): The address that receives the gas payment refund.

`_signatures` (bytes): The packed signature data.

`_msgSender` (address): The address of the transaction sender.

***

```solidity
function checkAfterExecution(
    bytes32 txHash, 
    bool success
) external view;
```

Performs checks after executing a transaction.

### Parameters:

`txHash` (bytes32): The hash of the executed transaction.

`success` (bool): Indicates the success status of the transaction.

***

```solidity
function isLocked(
    bytes32 _id
) external view returns (bool);
```

Checks if an asset is locked.

### Parameters:

`_id` (bytes32): The ID of the asset.&#x20;

### Returns:

(bool): Indicates whether the asset is locked or not.

***

```solidity
function getExpiry(
    bytes32 _id
) external view returns (uint256);
```

Returns the delegation expiry of an asset.

### Parameters:

`_id` (bytes32): The ID of the asset.&#x20;

### Returns:

(uint256): The delegation expiry timestamp of the asset.

***

```solidity
function setDelegationExpiries(
    address[] calldata _assets, 
    uint256[] calldata _ids, 
    uint256 _expiry
) external;
```

Sets the delegation expiry for a group of assets.

### Parameters:

`_assets` (address\[]): An array of asset addresses.

`_ids` (uint256\[]): An array of asset IDs.

`_expiry` (uint256): The delegation expiry timestamp.

***

```solidity
function setDelegationExpiry(
    address _asset, 
    uint256 _id, 
    uint256 _expiry
) external;
```

Sets the delegation expiry for a specific asset.

### Parameters:

`_asset` (address): The address of the asset.

`_id` (uint256): The ID of the asset.

`_expiry` (uint256): The delegation expiry timestamp.

***

```solidity
function lockAsset(bytes32 _id) external;
```

Sets an asset as locked.

### Parameters:

`_id` (bytes32): The ID of the asset.

***

```solidity
function unlockAsset(bytes32 _id) external;
```

Sets an asset as unlocked.

### Parameters:

`_id` (bytes32): The ID of the asset.

***

```solidity
function supportsInterface(
    bytes4 _interfaceId
) external view returns (bool);
```

Checks if the contract supports a specific interface.

### Parameters:

`_interfaceId` (bytes4): The interface ID to check.&#x20;

### Returns:

(bool): Indicates whether the contract supports the specified interface or not.

***

## Interactions:

* Interacts with the DelegationOwner, GuardOwner, and ProtocolOwner contracts to enforce specific rules and permissions.
* Validates transactions initiated through the GnosisSafe contract based on delegation and locking rules.


# DelegationRecipes

The DelegationRecipes contract registers and manages allowed functions for specific asset collections. It defines the rules and permissions for asset delegation within the Unlockd Wallet.&#x20;

## Key Functions:

```solidity
function add(
    address _collection, 
    address[] calldata _contracts, 
    bytes4[] calldata _selectors, 
    string[] calldata _descriptions
) external
```

Adds a group of allowed functions for a specific asset collection.

### Parameters:

`_collection` (address): The address of the asset collection.

`_contracts` (address\[]): An array of target contract addresses.

`_selectors` (bytes4\[]): An array of allowed function selectors.

`_descriptions` (string\[]): An array of function descriptions.

***

```solidity
function remove(
    address _collection, 
    address[] calldata _contracts, 
    bytes4[] calldata _selectors
) external
```

Removes a group of allowed functions from a specific asset collection.

### Parameters:

`_collection` (address): The address of the asset collection.

`_contracts` (address\[]): An array of target contract addresses.

`_selectors` (bytes4\[]): An array of function selectors to remove.

***

```solidity
function isAllowedFunction(
    address _collection, 
    address _contract, 
    bytes4 _selector
) external view returns (bool)
```

Checks if a function is allowed for a given asset collection.

### Parameters:

`_collection` (address): The address of the asset collection.

`_contract` (address): The address of the target contract.

`_selector` (bytes4): The function selector.

### Returns:

A boolean indicating whether the function is allowed for the asset collection.

***

## Interactions:

* Interacts with the DelegationOwner contract to determine allowed functions for asset delegation.


# AllowedControllers

The AllowedControllers contract manages the allowed delegation and lock controllers within the Unlockd Wallet. It determines which addresses are authorized to perform delegation and locking operations.&#x20;

## Key Functions:

<pre class="language-solidity"><code class="lang-solidity"><strong>function setCollectionAllowance(address _collection, bool _allowed) external;
</strong></code></pre>

Sets the allowance status of a collection controller.

### Parameters:

`_collection` (address): The address of the collection.

`_allowed` (bool): A boolean indicating whether the collection controller is allowed.&#x20;

### Interactions:

Emits the `Collections` event when the allowance status of a collection is set.

***

```solidity
function setCollectionsAllowances(
    address[] calldata _collections, 
    bool[] calldata _allowances
) external;
```

Sets the allowance statuses of multiple collection controllers.

### Parameters:

`_collections` (address\[]): An array of collection addresses.

`_allowances` (bool\[]): An array of allowance statuses corresponding to the collections.&#x20;

### Interactions:

Emits the `Collections` event for each collection allowance status set.

***

```solidity
function setDelegationControllerAllowance(
    address _controller, 
    bool _allowed
) external;
```

Sets the allowance status of a delegation controller.

### Parameters:

`_controller` (address): The address of the delegation controller.

`_allowed` (bool): A boolean indicating whether the delegation controller is allowed.&#x20;

### Interactions:

Emits the `DelegationController` event when the allowance status of a delegation controller is set.

***

```solidity
function setDelegationControllerAllowances(
    address[] calldata _controllers, 
    bool[] calldata _allowances
) external;
```

Sets the allowance statuses of multiple delegation controllers.

### Parameters:

`_controllers` (address\[]): An array of delegation controller addresses.

`_allowances` (bool\[]): An array of allowance statuses corresponding to the controllers.&#x20;

### Interactions:

Emits the `DelegationController` event for each delegation controller allowance status set.

***

```solidity
function isAllowedCollection(
    address _collection
) external view returns (bool);#
```

Checks if a collection address is allowed

### Parameters:

`_collection` (address): The address of the collection.&#x20;

### Returns:

(bool): A boolean indicating whether the collection is allowed.

***

```solidity
function isAllowedDelegationController(address _controller) external view returns (bool);
```

Checks if an address is an allowed delegation controller.

### Parameters:

`_controller` (address): The address of the delegation controller.&#x20;

### Returns:

(bool): A boolean indicating whether the delegation controller is allowed.


# Deployed Contracts


# Ethereum Sepolia (Testnet)

The addresses deployed to Ethereum Sepolia

<table><thead><tr><th width="272.3333333333333">Name</th><th>Addresses</th></tr></thead><tbody><tr><td>DelegationWalletFactory</td><td>0x6ff8191bd9c350e63291cf68ce157bb663966642</td></tr><tr><td>DelegationWalletRegistry</td><td>0x03afe3e023862ef439bca0b2e76de040ad62ddf0</td></tr><tr><td>DelegationOwner</td><td>0x775a196574340409fe67cc2e09cb5702beac6b94</td></tr><tr><td>GuardOwner</td><td>0xe648dc053117602b01c379db8a02beac69e17bc9</td></tr><tr><td>ProtocolOwner</td><td>0x0ea52253b2e47e52615ed78bc0d863abbcb02cfd</td></tr><tr><td>TransactionGuard</td><td>0x9ef329ef030788975095c11a50a7b25ddaaa15fe</td></tr><tr><td>DelegationRecipes</td><td>0x864b9649b3a47e1b64e3c5459d90022de1f3aa7e</td></tr><tr><td>AllowedControllers</td><td>0xa5b9a2816e26622c471f0214925dbba217dcca59</td></tr></tbody></table>


# Best Practices

As a developer working with the Unlockd Protocol or any DeFi project, it is crucial to follow best practices to ensure the security, stability, and efficiency of your integration.

## Code Quality

1. **Smart contract audits**: Before deploying any smart contract to the mainnet, ensure it has been thoroughly reviewed and audited by reputable security firms. This minimizes the risk of vulnerabilities and exploits.
2. **Code modularity and readability**: Write modular and well-structured code to make it easy for other developers to understand, review, and contribute to your project. This includes using appropriate naming conventions, commenting, organizing your codebase, and following established programming paradigms.
3. **Testing**: Implement comprehensive test suites for your smart contracts, including unit tests, integration tests, and end-to-end tests. This ensures that your code behaves as expected and helps catch potential bugs or issues.
4. **Continuous integration and deployment**: Set up a CI/CD pipeline to automatically build, test, and deploy your code. This helps catch integration issues early and streamlines the development process.

## Interaction with External Contracts

1. **Use trusted and audited contracts**: When interacting with third-party contracts or libraries, ensure they have been audited and are widely trusted within the ecosystem.
2. **Handle external contract calls safely**: Be cautious when making external contract calls. Assume that any external contract can be malicious, and handle reentrancy attacks, untrusted callbacks, and gas limits accordingly. Use the "checks-effects-interactions" pattern to minimize risks.
3. **Manage contract upgrades**: Plan for the potential need to upgrade your smart contracts in the future. Design your contracts to be upgradeable or use proxy patterns, but always keep in mind the trade-offs and security implications.

## Gas Optimization

1. **Optimize for gas usage**: Write efficient smart contract code to minimize gas costs for users. This may include using appropriate data structures, minimizing storage writes, and taking advantage of compiler optimizations.
2. **Batch transactions**: When possible, batch multiple transactions together to reduce gas costs and improve the overall user experience.
3. **Monitor gas prices**: Keep track of the current gas prices and suggest optimal gas fees to users for a balance between cost and transaction speed.

## Decentralization and Governance

1. **Embrace decentralization**: Strive to decentralize the control and decision-making processes of your DeFi project. This increases trust and helps prevent single points of failure.
2. **Implement governance mechanisms**: Incorporate governance tokens and mechanisms to give users a say in the development and management of your platform.
3. **Ensure transparency**: Make your project's code, documentation, and governance processes open and transparent to the community. This fosters trust and encourages engagement from users and developers alike.


# Security and Risk Management

Prioritizing security and risk management is crucial when working with DeFi protocols. Here are some guidelines to consider:

## Smart Contract Security

1. **Use established patterns**: Whenever possible, use established and secure design patterns for your smart contracts. For example, use the OpenZeppelin library for implementing ERC20 tokens or standard access control mechanisms.
2. **Minimize complexity**: Keep your smart contracts as simple as possible. Complexity increases the chances of introducing vulnerabilities and makes it harder to audit and verify the code's correctness.
3. **Monitor and respond to vulnerabilities**: Stay informed about new vulnerabilities discovered in the DeFi ecosystem and apply patches or updates as needed. Be prepared to react to potential threats to your smart contracts.
4. **Use formal verification**: Apply formal verification techniques to validate the correctness of your smart contract code. This can help identify potential issues and ensure that the contracts meet their intended specifications.
5. **Secure randomness**: If your smart contract requires random numbers, use secure and decentralized sources of randomness, such as Chainlink's VRF (Verifiable Random Function) or similar solutions

## User Protection

1. **Ensure proper access control**: Implement appropriate access controls for your smart contracts, such as role-based access control (RBAC) or the use of multi-signature wallets for critical functions.
2. **Provide transparent information**: Clearly communicate the risks and mechanics of your platform to users. This includes providing thorough documentation, terms of service, and risk disclaimers.
3. **Implement emergency mechanisms**: Design your smart contracts with emergency mechanisms, such as circuit breakers or pause functions, to halt operations in case of an unexpected issue or vulnerability.
4. **Protect user privacy**: Consider incorporating privacy-enhancing technologies like zero-knowledge proofs (ZKPs) to protect user data and transactions.
5. **Educate users**: Offer resources and guidance to help users understand the importance of safe practices, such as using hardware wallets, keeping private keys secure, and enabling two-factor authentication (2FA).

## Risk Management

1. **Monitor platform activity**: Regularly monitor the activity and performance of your DeFi platform. Set up alerts and monitoring tools to track unusual behavior or potential exploits.
2. **Establish risk management processes**: Develop clear processes and procedures for managing risks within your platform, such as collateral management, liquidation policies, and interest rate adjustments.
3. **Consider insurance**: Encourage users to utilize smart contract insurance services like Nexus Mutual or Bridge Mutual to protect their assets against potential losses from exploits or vulnerabilities.
4. **Perform stress tests and simulations**: Conduct stress tests and simulations on your platform to evaluate its resilience under extreme market conditions or high network congestion.
5. **Maintain a bug bounty program**: Implement a bug bounty program to incentivize responsible disclosure of vulnerabilities and security issues by external researchers. Find ours [here](https://immunefi.com/bounty/unlockd/).


