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 slashing
└── Community monitoring
Layer 4: Admin Controls
├── 24-hour timelock on sensitive functions
├── Multisig owner (recommended)
├── No emergency withdrawal of user funds
└── Pausable for emergenciesSmart 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 functionsonlyOwnerOrTimelock: Sensitive admin functions requiring timelockonlyLendingCore: 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:
| Function | Timelock Required | Delay |
|---|---|---|
| Set platform fee | Yes | 24 hours |
| Set collateral guard | Yes | 24 hours |
| Set liquidation module | Yes | 24 hours |
| Set deposit manager | Yes | 24 hours |
| Pause/Unpause | No | Immediate |
How Timelock Works
- Admin queues a transaction
- 24-hour waiting period
- Anyone can monitor queued transactions
- Admin executes after delay
- 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 → BLOCKWhat the Guard Blocks
transferFromfor locked tokenssafeTransferFromfor locked tokensapprovefor locked tokenssetApprovalForAllwhen any tokens are lockedburnfor locked tokens- Removing the guard while loans active
- Disabling the module while loans active
Pre-Loan Checks
Before creating a Safe Guard loan:
- Guard must be installed
- Liquidation Module must be enabled
- No other modules allowed
- 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
// 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 - DepositIf 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
- Slashes deposit if cheating detected
No Automated Monitoring
Currently, detection relies on community monitoring. Lenders should:
- Monitor their loans
- Or use keeper services
- Or accept the delayed detection risk
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
| Auditor | Date | Status | Report |
|---|---|---|---|
| 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 to: [security email]
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
- Pause the protocol (if needed)
- Assess impact
- Communicate with users
- Deploy fix (if possible) or mitigate
- Post-mortem
Emergency Contacts
- Discord: [link]
- Email: [security email]
- Twitter: [link]
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 logicsrc/guards/TDHCollateralGuard.sol- Safe Guard implementationsrc/modules/TDHLiquidationModule.sol- Safe Module for liquidationsrc/core/TDHDepositManager.sol- Deposit escrowsrc/core/TDHAdditionalCollateral.sol- Additional collateral escrowsrc/core/TDHTimelock.sol- Admin timelock
We welcome security reviews from the community.