Skip to content

Security ​

This page describes the security measures in NFT Loans and our approach to keeping your funds safe.


Security Architecture ​

Defense in Depth ​

Multiple layers of security protect users:

Layer 1: Smart Contract Design
├── Reentrancy guards on all external calls
├── Checks-effects-interactions pattern
├── Access control on privileged functions
└── Input validation

Layer 2: Safe Integration
├── Guard blocks locked NFT transfers
├── Module limited to liquidation only
├── Setup verification before loans
└── 24-hour activation delay

Layer 3: Economic Security (Deposit Mode)
├── 20% deposit requirement
├── Cheating detection and deposit payout to lender
└── Keeper and community monitoring

Layer 4: Admin Controls
├── 24-hour timelock on sensitive functions
├── Secure owner wallet required for operations
├── No emergency withdrawal of user funds
└── Pausable for emergencies

Layer 5: Compliance Gate
├── Server-side wallet sanctions screening during onboarding
├── Optional legal/business/counterparty name screening
├── Screening records stored in private service-role tables
└── Manual review for non-clear name results

Onboarding Compliance Screening ​

Wallet onboarding is gated by a server-side ScreenLayer check. The app calls ScreenLayer from the Next.js API route only, using SCREENLAYER_API_KEY; this key must never be exposed with a NEXT_PUBLIC_ prefix or used in browser code.

The onboarding screening route requires a fresh wallet signature over the screened wallet, customerRef, request origin, and issued-at timestamp before it calls ScreenLayer or writes compliance records. Existing customerRef rows can only be updated by the same wallet address, so a client cannot rebind another onboarding record to a different wallet.

Onboarding can continue only when wallet screening returns clear. Blocked wallet results create a compliance review case and stop onboarding. Name results that require review hold onboarding for manual review and are not treated as a final legal determination.


Smart Contract Security ​

Reentrancy Protection ​

All external calls use OpenZeppelin's ReentrancyGuard. Functions that transfer ETH or interact with external contracts are protected.

Access Control ​

  • onlyOwner: Admin functions
  • onlyOwnerOrTimelock: Sensitive admin functions requiring timelock
  • onlyLendingCore: Functions only callable by the core contract

Safe Math ​

Solidity 0.8+ provides built-in overflow/underflow protection.

No Upgradability ​

Contracts are NOT upgradeable. This prevents:

  • Admin changing contract logic
  • Proxy-related vulnerabilities
  • Storage collision issues

The tradeoff: bugs cannot be easily fixed. We rely on thorough testing.


Timelock ​

Sensitive admin functions must go through the timelock:

FunctionTimelock RequiredDelay
Set platform feeYes24 hours
Set collateral guardYes24 hours
Set liquidation moduleYes24 hours
Set deposit managerYes24 hours
Pause/UnpauseNoImmediate

How Timelock Works ​

  1. Admin queues a transaction
  2. 24-hour waiting period
  3. Anyone can monitor queued transactions
  4. Admin executes after delay
  5. 14-day grace period to execute

This gives the community time to react to malicious changes.


Safe Guard Security ​

What the Guard Checks ​

Every transaction from a protected Safe is inspected:

Transaction
    ↓
Is it to an NFT contract?
    ├── No → Allow
    └── Yes ↓
        Is it a transfer/approve/burn?
            ├── No → Allow
            └── Yes ↓
                Is the token locked?
                    ├── No → Allow
                    └── Yes → BLOCK

What the Guard Blocks ​

  • transferFrom for locked tokens
  • safeTransferFrom for locked tokens
  • approve for locked tokens
  • setApprovalForAll when any tokens are locked
  • burn for locked tokens
  • Removing the guard while loans active
  • Disabling the module while loans active

Pre-Loan Checks ​

Before creating a Safe Guard loan:

  1. Guard must be installed
  2. Liquidation Module must be enabled
  3. No other modules allowed
  4. No existing approvals on the NFT

Liquidation Module Security ​

Limited Scope ​

The module can ONLY:

  • Transfer a specific NFT
  • To a specific recipient
  • When called by TDHLendingCore
  • When loan is validly defaulted

Cannot ​

  • Transfer other assets
  • Execute arbitrary calls
  • Be called by anyone except LendingCore
  • Act before default conditions met

Verification ​

solidity
// Module checks before executing
require(msg.sender == lendingCore, "Only lending core");
require(!liquidationExecuted[loanId], "Already executed");
// LendingCore checks before calling
require(loan.status == ACTIVE, "Loan not active");
require(isDefaulted(loanId), "Not defaulted");

24-Hour Activation Delay ​

Safe Guard loans have a waiting period after creation:

Purpose ​

  • Detect if NFT was transferred before loan setup
  • Catch setup manipulation attempts
  • Give time to cancel suspicious loans

What's Checked at Activation ​

  • Borrower still owns the NFT
  • NFT is still locked in the guard
  • No bypass detected

Cancellation ​

Anyone can cancel a pending loan if:

  • Borrower no longer owns the NFT
  • Lock was somehow bypassed

Lender's funds are returned on cancellation.


Deposit Mode Security ​

Economic Security Model ​

The 20% deposit makes cheating costly but not impossible:

Cheating profit = Borrowed ETH + NFT value - Deposit

If NFT is worth more than 5x the deposit, cheating is profitable. This is why:

  • Deposit Mode has higher interest rates
  • Lenders should price this risk
  • Safe Guard Mode is recommended for larger loans

Cheating Detection ​

Anyone can report cheating via reportCheating(loanId):

  • Checks if borrower owns NFT
  • Checks if approval is valid
  • Pays the escrowed deposit to the lender if cheating is detected

Automated Keeper Monitoring ​

The services package includes keeper monitoring for activation, liquidation, and Deposit mode cheating checks. This is helpful but not a guarantee. Lenders should still:

  • Monitor their loans
  • Understand that anyone can call the public keeper functions
  • Accept the delayed detection risk if keepers or RPC providers are down

Known Limitations ​

setApprovalForAll ​

We can check getApproved(tokenId) but cannot enumerate all operators from isApprovedForAll. Users must revoke these manually before borrowing.

Pre-existing Modules ​

We check that the Safe has exactly one module (ours), but we rely on the user having removed others. A determined attacker with Safe admin access could potentially add modules between checks and loan creation.

Deposit Sizing ​

The 20% deposit is based on principal, not NFT value. If NFT floor is much higher than principal, cheating economics favor the borrower.

Oracle Centralization ​

Additional collateral floor prices are admin-set, not oracle-fed. This requires trust in the admin.


Audit Status ​

AuditorDateStatusReport
Pending---

We recommend waiting for audit completion before depositing significant funds.


Bug Bounty ​

We're planning a bug bounty program. Details coming soon.

In the meantime, please report security issues through the private GitHub advisory form: https://github.com/maybehotcarl/nftloans/security/advisories/new

Responsible Disclosure ​

  • Do not exploit vulnerabilities
  • Give us reasonable time to fix
  • Do not disclose publicly until fixed

Incident Response ​

If a Vulnerability is Found ​

  1. Pause the protocol (if needed)
  2. Assess impact
  3. Communicate with users
  4. Deploy fix (if possible) or mitigate
  5. Post-mortem

Emergency Contacts ​


Security Checklist for Users ​

Before Using ​

  • [ ] Verify contract addresses match docs
  • [ ] Check contracts are verified on Etherscan
  • [ ] Understand the risks (read this page!)
  • [ ] Start with small amounts

For Borrowers (Safe Guard) ​

  • [ ] Use a dedicated Safe for borrowing
  • [ ] Remove other modules before setup
  • [ ] Revoke existing NFT approvals
  • [ ] Verify guard and module are installed

For Borrowers (Deposit) ​

  • [ ] Understand deposit is at risk
  • [ ] Don't transfer the NFT
  • [ ] Don't revoke approval
  • [ ] Repay on time

For Lenders ​

  • [ ] Prefer Safe Guard Mode
  • [ ] Don't over-concentrate in one loan
  • [ ] Monitor Deposit mode loans
  • [ ] Understand NFT liquidation risk

Code Review ​

The source code is available at: [GitHub link]

Key files to review:

  • src/core/TDHLendingCore.sol - Main lending logic
  • src/guards/TDHCollateralGuard.sol - Safe Guard implementation
  • src/modules/TDHLiquidationModule.sol - Safe Module for liquidation
  • src/core/TDHDepositManager.sol - Deposit escrow
  • src/core/TDHAdditionalCollateral.sol - Additional collateral escrow
  • src/core/TDHTimelock.sol - Admin timelock

We welcome security reviews from the community.

Built for the 6529 community