1Do App
NFT Market
A maker signs a specific NFT and consideration offchain; a buyer settles atomically with a transient token/NFT pull or exact native value.
Market model
NFT Market is a signed-order market for specific ERC-721 tokenIds. Orders are created and distributed offchain, assets remain in both wallets before settlement, and only fills or cancellations write order state onchain.
The current implementation is full-fill and peer-to-peer. It does not include auctions, partial fills, collection-wide bids, NFT bundles, ERC-1155, royalties, or a market protocol fee.
Five order types
- NftForTokenOrder: the maker provides a specified NFT and the buyer pays ERC-20.
- TokenForNftOrder: the maker provides ERC-20 and the buyer pays a specified NFT.
- NftForNativeOrder: the maker provides a specified NFT and the buyer pays native currency.
- NativeForNftOrder: the maker provides native currency and the buyer pays a specified NFT.
- NftForNftOrder: maker and buyer exchange the two exact NFTs identified by the order.
- expiry = 0 means no contract-level expiry. nonce is an order salt rather than an incrementing account nonce, and tokenId 0 is valid.
struct NftForTokenOrder {
address nft;
uint256 tokenId;
address erc20;
uint256 tokenAmount;
uint256 expiry;
uint256 nonce;
}
struct TokenForNftOrder {
address nft;
uint256 tokenId;
address erc20;
uint256 tokenAmount;
uint256 expiry;
uint256 nonce;
}
struct NftForNativeOrder {
address nft;
uint256 tokenId;
uint256 nativeAmount;
uint256 expiry;
uint256 nonce;
}
struct NativeForNftOrder {
address nft;
uint256 tokenId;
uint256 nativeAmount;
uint256 expiry;
uint256 nonce;
}
struct NftForNftOrder {
address giveNft;
uint256 giveTokenId;
address wantNft;
uint256 wantTokenId;
uint256 expiry;
uint256 nonce;
}Signature and settlement flow
Sign the exact order
The maker uses the EIP-712 domain NFT Market Order on 1Do / 1 with the maker wallet as verifyingContract.
Prepare buyer assets
ERC-20 or NFT payment uses a one-call pull from the buyer wallet; native payment is attached directly to the maker Runtime call.
Validate maker intent
The app checks fields, expiry, consumed state, and the maker signature through wallet ERC-1271.
Exchange atomically
The order is consumed and both assets move in one transaction. Any pull, transfer, or signature failure reverts everything.
Asset paths
- NFT → Token: the buyer token-pulls ERC-20 to the maker, and the app sends the maker NFT to the buyer.
- Token → NFT: the buyer NFT-pulls the specified NFT to the maker, and the app sends maker ERC-20 to the buyer.
- NFT → Native: the buyer attaches exact msg.value, and the app sends the maker NFT to the buyer.
- Native → NFT: the buyer NFT-pulls the specified NFT to the maker, and the app sends native currency from the maker wallet.
- NFT → NFT: the buyer NFT-pulls wantNft to the maker, and the app sends giveNft to the buyer.
- Token/NFT pull paths require the matching pull capability in the buyer wallet but do not require the buyer to enable NFT Market. The maker must enable the current market logic and Registry must still allow it.
Cancellation, events, and state
- The maker wallet can self-call the exact cancellation function for each order type. Fill and cancellation consume the full order; there is no nonce floor or batch cancellation.
- The order binds neither a designated buyer nor the app logic address. Any buyer may submit a valid fill, so logic-version changes require an old-signature compatibility review.
- There is no public consumedOrders getter. Indexers should listen for Filled / Cancelled events at the maker wallet and combine them with simulation.
- The maker wallet emits the events. NftForToken and TokenForNft use the full EIP-712 digest, while both native order types and NftForNft use the struct hash.
- Removing an offchain listing is not an onchain cancellation. Disabling the app does not erase an order; an unexpired, unconsumed signature may work again after re-enablement.
Recipient and asset boundaries
- When the buyer supplies an NFT, the wallet pull path uses safeTransferFrom into the maker wallet.
- When the maker supplies an NFT, the app uses transferFrom to the buyer and does not invoke ERC721Receiver. Contract buyers must ensure they can safely hold the NFT.
- Native payment must exactly match the signed amount, and a native recipient rejection reverts the trade.
- ERC-20 transfers use SafeERC20. Fee-on-transfer, rebasing, and other nonstandard balance semantics have no dedicated adaptation.
Orders cover exact assets
NFT Market leaves no reusable ERC-20 allowance or NFT operator for the app logic, but a valid fill moves the exact signed assets. Review contract addresses, tokenIds, amounts, chain, and maker wallet before signing.