Overview
Clutch.AMM is a permissionless NFT liquidity protocol deployed on ApeChain and Ethereum Mainnet. Markets can be deployed as either single-collection or multi-collection configurations. In multi-collection markets, collections share one token + escrow while each linked collection keeps its own AMM/loan/staking vault set. Linked collections are immutable after deployment.
The core idea: each market defines a fixed base exchange ratio (tokensPerNFT) between NFTs and its market token. The AMM quotes buys/sells around that base with fee logic. Borrowers can lock NFTs and receive market tokens immediately. Stakers earn a share of swap fees generated in the same market.
Key Properties
- →No token release outside deterministic, audited paths.
- →Global solvency invariant checked on every release.
- →Pausable fail-safe for critical paths. Protocol admin holds PAUSER_ROLE and DEFAULT_ADMIN_ROLE for emergency controls.
- →Most market parameters are immutable after deployment. Swap fees may be adjusted via on-chain governance if the market was deployed with governance enabled.
- →Random buy selection uses on-chain FIFO inventory ordering (oldest deposited first).
AMM & Swapping
The NFTAMMVault maintains an inventory of NFTs and a corresponding token balance. Prices are derived from the floor price of NFTs already deposited. When you sell an NFT, the vault mints/releases tokens from the escrow reserve and delivers them to you (minus fees). When you buy, you pay tokens and receive an NFT from inventory.
Sell an NFT
Deposit your NFT into the vault and receive market tokens immediately. The payout equals the floor price minus swap fees. No slippage risk: set a minPayout floor to protect against last-second price movement.
sellNFT(uint256 tokenId, uint256 minPayout) → Reverts: SlippageExceeded if payout < minPayout → Reverts: NotOwner / NotApproved / WrongCollection
Buy Random NFT
Pay market tokens to receive a random NFT from the vault's inventory. Random selection uses FIFO inventory ordering on-chain (oldest deposited, first bought). The market's swap fee (randomFeeBps, configurable 1–15%) applies.
buyRandomNFT(uint256 maxCost) → Reverts: EmptyInventory / SlippageExceeded if cost > maxCost
Buy Specific NFT
Pay a higher fee (specificFeeBps, which must be ≥ randomFeeBps) to select a specific NFT from the vault by token ID. This prevents gaming the rarity floor while still allowing targeted buys for collectors.
buySpecificNFT(uint256 tokenId, uint256 maxCost) → Reverts: NotInInventory / SlippageExceeded
Fee Structure
randomFeeBps, specificFeeBps) are set per market at deployment and distributed to stakers proportionally to their NFT stake weight. Protocol fees go to the Clutch DAO treasury.Borrowing
Lock your NFT as collateral and receive market tokens instantly. The loan is fixed-term: you choose a duration between 1 and 365 days. Interest accrues at the market's fixed APY. Repay the principal plus accrued interest before the grace period ends to retrieve your NFT.
How it works
- →Open a loan: your NFT is escrowed in the LoanVault for the loan duration.
- →Receive tokens: principal is released from the Loan bucket of the escrow reserve.
- →Repay: return principal + interest before maturity + 7-day grace period.
- →NFT returned: once repayment is confirmed, your NFT is released back to your wallet.
- →Liquidation: if unpaid after the grace period, any address can liquidate and earn a 2% incentive.
Loan Parameters
Contract Signatures
borrow(uint256 tokenId, uint256 duration) → Reverts: DurationTooShort / DurationTooLong / MaxLoansExceeded repay(uint256 loanId) → Repays principal + interest; returns NFT → Reverts: LoanNotActive / NotBorrower liquidate(uint256 loanId) → Permissionless after grace period; caller receives 2% incentive → Reverts: GraceNotExpired / LoanNotActive getLoanDetails(uint256 loanId) → Returns borrower, tokenId, principal, maturity, graceDeadline, status
Staking & Rewards
Deposit your NFTs into the NFTStakingVault to earn a continuous share of all swap fees generated by the market. Rewards accumulate in real-time and can be claimed at any time as market tokens.
Reward Sources
Staking Lifecycle
- →Stake: transfer NFT into the staking vault. Start accumulating rewards immediately.
- →Claim: call claimRewards() at any time to receive accumulated market tokens.
- →Unstake: call unstake(tokenId) after the 24-hour cooldown has elapsed.
- →Return: unstake transfers your NFT back to your wallet in the same transaction.
stake(uint256 tokenId) unstake(uint256 tokenId) // requires cooldown to be elapsed claimRewards() // claim accumulated market tokens pendingRewards(address user)
Create a Market
Any ERC-721 collection on a supported chain can have a Clutch.AMM market deployed for it. ERC-1155 support is available at the contract level; UI support is coming soon. Markets are permissionless — no approval needed. Multiple independent markets can exist for the same collection (each with its own parameters). The factory assigns each market a unique incrementing ID and deploys a fresh set of contracts for every market.
Deployment Process
- Provide the primary collection address, then optionally add more collections for a multi-collection market.
- Define the collection token name, symbol, and how many tokens each NFT is worth.
- Set fee parameters: random buy fee, specific buy fee, and borrow APY. Protocol fee is fixed at 0.5%.
- Pay the deployment fee (if any) to the factory. The fee is set by the protocol admin and may be zero.
- The factory deploys all required contracts (token, escrow, AMM vault, loan vault, staking vault — plus an optional governance contract), mints the total supply into escrow, and registers the market with a unique ID.
Deployment Parameters & Bounds
Solvency & Safety
The protocol enforces a global solvency invariant on every token release. The invariant guarantees that the total tokens in circulation can never exceed the tokens held in escrow minus the permanently locked portion. It is checked on every call to the TokenEscrowReserve and monitored off-chain by the risk engine.
The Invariant
// Must hold at all times (checked in TokenEscrowReserve.release() and returnTokens()): escrow.balanceOf(escrow) + totalReleased >= totalSupply // In plain terms: tokens held in escrow + tokens already out ≥ total minted. // Protects against any out-of-thin-air token release. // If this check fails, the transaction reverts with InvariantViolation.
Bucket Architecture
Token releases are gated by three isolated buckets. Each bucket has a hard cap. Once a bucket reaches its cap, no further releases from that path are possible, protecting the other paths.
Fail-Safes
- Emergency pause: any vault can be paused by the protocol admin (PAUSER_ROLE). Unpausing requires DEFAULT_ADMIN_ROLE.
- Bucket caps: each release path (AMM, Loan, Reward) has a hard cap set at deployment; once reached, no further releases from that path.
- Invariant breach: if the global invariant fails after any release, the transaction reverts automatically with InvariantViolation.
- Liquidation bot: open-source reference liquidator monitors all loans for expiry.
- No admin drain: escrow only releases tokens via authorized vault contracts. The admin cannot withdraw tokens directly.
Smart Contracts
The table below shows the contracts currently configured in this frontend environment. For local Anvil sessions, these are local development addresses. The factory is the single entry point for deploying new markets.
Deployed Addresses
Key Function Reference
// Factory
struct CreateMarketParams {
address collection;
string name;
string symbol;
uint256 tokensPerNFT;
uint256 totalSupply;
FeeConfig fees; // { randomFeeBps, specificFeeBps }
BucketConfig buckets; // { ammBps, loanBps, rewardBps } — must sum <= 100%
uint16 borrowAPYBps;
uint16 liquidationIncentiveBps;
GovernanceParams governance; // { enabled, proposalFee, minProposerStake }
}
struct CreateMultiCollectionParams {
string name;
string symbol;
uint256 totalSupply;
BucketConfig buckets;
uint16 liquidationIncentiveBps;
GovernanceParams governance;
CollectionConfig[] collections; // per-collection: { collection, tokensPerNFT, fees, borrowAPYBps }
}
createMarket(CreateMarketParams p) payable → MarketInfo
createMultiCollectionMarket(CreateMultiCollectionParams p) payable → MarketInfo
allMarkets() view → MarketInfo[]
marketCount() view → uint256
getCollectionsForMarket(uint256 marketId) view → address[]
getCollectionVaultInfo(uint256 marketId, address collection) view → CollectionVaultInfo
// NFTAMMVault
sellNFT(uint256 tokenId, uint256 minPayout)
buyRandomNFT(uint256 maxCost)
buySpecificNFT(uint256 tokenId, uint256 maxCost)
quoteRandomBuy() view → (totalCost, baseCost, fee, protocolFee, inventorySize, nextTokenId)
quoteSpecificBuy(uint256 tokenId) view → (totalCost, baseCost, fee, protocolFee, available)
// LoanVault
borrow(uint256 tokenId, uint256 duration)
repay(uint256 loanId)
liquidate(uint256 loanId)
getLoanDetails(uint256 loanId) view → LoanInfo
// NFTStakingVault
stake(uint256 tokenId)
unstake(uint256 tokenId)
claimRewards()
pendingRewards(address user) view → uint256UI Metrics Note
Market cap is displayed as a token-denominated value using the market's native token symbol (e.g. 21.89M TEST). For multi-collection markets, the label reads Est. Market Cap because capacity is derived from shared escrow sizing rather than per-collection hard allocation. TVL is shown as the number of NFTs currently held in protocol vaults.
Token Logo Guide
When you deploy a new market, the protocol creates a brand-new ERC-20 token for your collection. By default, wallets and block explorers will show a placeholder icon. Follow these steps to get your token logo displayed across the ecosystem.
How Clutch.AMM resolves token logos
The app tries the following sources in order, using the first one that loads successfully:
Option 1: Self-host (instant)
This is the fastest path. Host a square PNG or SVG anywhere (IPFS, Arweave, GitHub, CDN), then paste the URL into the Token Logo field when creating your market. The URL is stored in our backend and shown everywhere on Clutch.AMM immediately.
# Good logo URLs: https://ipfs.io/ipfs/QmXxx.../logo.png https://arweave.net/TXID/logo.png https://raw.githubusercontent.com/yourorg/assets/main/cpup.png https://cdn.yourproject.com/token-logo.png
Option 2: Block Explorer (recommended)
Your chain's block explorer (ApeScan for ApeChain, Etherscan for Ethereum) allows token issuers to upload a logo that appears on the token page and in MetaMask's token import flow.
- 1.Deploy your market (this creates the ERC-20 token on-chain).
- 2.Go to your chain's block explorer and search for your token contract address.
- 3.Click 'Update Token Info' on the token page.
- 4.Fill in the token info form and upload your logo PNG (max 1MB, square).
- 5.Submit. Verification usually takes 24-48 hours.
Option 3: Trust Wallet Assets
Trust Wallet maintains an open-source repository of token logos used by Trust Wallet, MetaMask, and many other wallets. Getting listed here gives the broadest ecosystem coverage.
# Repository structure:
trustwallet/assets/
blockchains/
apechain/
assets/
0xYourTokenAddress/ ← checksummed ERC-55 address
logo.png ← 256×256px, max 100KB
# Steps:
1. Fork https://github.com/trustwallet/assets
2. Create the directory at the path above
3. Add your logo.png (256×256, transparent bg)
4. Open a Pull Request — usually merged in 1–3 daysethers.getAddress(address) to get the correct casing.After listing
Once your logo is live anywhere (self-hosted URL, ApeScan, or Trust Wallet), update your market's token logo URL in the market metadata editor (owner-only on the market page) or set it during market creation. The change propagates site-wide immediately.
Risk Disclosure
Smart Contract Risk
Despite thorough testing and audit processes, all smart contracts carry the risk of undiscovered vulnerabilities. A bug could result in partial or total loss of funds.
Liquidation Risk
If you take out a loan and do not repay before the grace period ends, your NFT collateral will be permanently liquidated. There is no recovery mechanism. The liquidation is irreversible on-chain.
Market Risk
NFT floor prices can move rapidly. A sharp decline in floor price reduces the collateral value of your NFT. While Clutch.AMM uses fixed-rate loans (not mark-to-market LTV), the token payout you receive when selling is directly tied to current floor conditions.
Liquidity Risk
If the vault's NFT inventory is empty, random and specific buys will fail until new NFTs are deposited. If the escrow bucket reaches its cap, swaps in that direction may temporarily be unavailable.
Oracle & Randomness Risk
Random buy selection uses FIFO inventory ordering (oldest deposited, first purchased). This avoids external oracle dependencies, but users should still assume NFT purchase outcomes depend on current vault inventory state at execution time.
Audit
Clutch.AMM contracts have undergone a comprehensive security audit covering all 14 Solidity source files (2,779 SLOC) across the factory, market, vault, governance, router, and library modules. The audit has been certified by Hashlock.