NFTfi Integration
NFTfi is a peer-to-peer NFT lending protocol. A borrower locks an NFT in a smart contract, receives ETH or USDC from a specific lender, and agrees to return it after a fixed term with interest. Failure to return means the NFT transfers to the lender. No liquidation oracle, no AMM: a pure fixed-term loan with NFT as collateral.
Integration is needed in two scenarios: you are building a lending platform on top of NFTfi, or you want to give your marketplace or NFT project users the ability to borrow directly from the interface.
Protocol Architecture and Integration Points
NFTfi works through two key contracts: NftfiHub (registry and router) and DirectLoanFixedOffer (a specific loan type with fixed rates). Since v2.1, the protocol added DirectLoanFixedOfferRedeploy with ERC-1155 support.
The main flow:
-
Borrower calls
approvefor the NFT at the NFTfi contract address, then accepts an offer viaacceptOffer - Lender creates a signed off-chain offer (EIP-712 structured data) stored in the NFTfi database or your backend
- Upon
acceptOffer, the contract transfers the NFT to itself, sends tokens to the borrower, and mints a promissory note NFT (ERC-721) as an obligation for the lender - After expiration:
payBackLoanby the borrower orliquidateOverdueLoanby the lender
Offer Structure (EIP-712)
Integrating through offer signatures is where most mistakes happen. The offer contains:
struct Offer {
uint256 loanPrincipalAmount;
uint256 maximumRepaymentAmount;
uint256 nftCollateralId;
address nftCollateralContract;
uint32 loanDuration; // in seconds
uint16 loanAdminFeeInBasisPoints;
address loanERC20Denomination;
address referrer;
}
Signature is created via signTypedData in ethers.js or viem, using the domain separator of the NFTfi contract. Critical: the domain separator includes chainId—an offer signed for Ethereum mainnet is invalid on Goerli, even if the contract address matches.
Common Mistake: Handling Intermediate Loan States
A loan can be in states: Active, Repaid, Liquidated, or an edge case where a payBackLoan block mines after loanDuration expires, but liquidateOverdueLoan hasn't been called yet. The contract accepts both calls in a short window. If the frontend doesn't update status atomically, users see an active loan that's already liquidated.
Solution: listen to LoanStarted, LoanRepaid, LoanLiquidated events via ethers.js provider.on or subscriptions via The Graph subgraph (NFTfi supports an official subgraph). Subgraph is preferable for UI—it allows complex queries (all active loans per collection, address loan history).
What's Included in Integration
SDK / Library. NFTfi provides an official JavaScript SDK (@nftfi/js) that abstracts contract interactions. For custom integrations, working directly through the ABI is often simpler—full control over parameters and gas estimation.
Subgraph queries. GraphQL to fetch active offers, loan history, collection data. Integrate via @apollo/client or urql.
Loan currencies. NFTfi supports ETH, USDC, DAI, and other approved ERC-20s. You need approve logic for each currency from the lender before creating an offer.
Referral system. The protocol supports a referrer address in offers—a way to monetize integration through protocol commissions.
Work Process
ABI Learning and Goerli Testing (1 day). Deploy a test NFT, create a loan manually through the contract, verify all events.
Backend Integration (1-2 days). Offer storage and translation, webhooks on loan events.
Frontend Components (1-2 days). Offer creation form, display of active loans, repayment flow.
Timeline Estimates
Basic integration—creating and accepting offers, monitoring loans: 3-5 days. Full lending UI with collection analytics and auto-generated offers: 1-1.5 weeks.







