# Phrase Trade NFT Marketplace

### Overview

The `PhraseTradeNFTMarketplace` is a Solidity smart contract that implements a decentralized marketplace for trading Non-Fungible Tokens (NFTs). This contract allows users to list their NFTs for sale, buy listed NFTs, and delist their own NFTs. It supports payments in both Ether (ETH) and ERC-20 tokens.

### Contract Details

* **License**: BSUL
* **Solidity Version**: ^0.8.0
* **Inherits From**:
  * `Ownable`: Provides basic authorization control functions
  * `IPhraseTradeNFTMarketplace`: Interface defining the contract's structure

### Key Structures

#### Listing

```solidity
struct Listing {
    address seller;
    address paymentToken;
    uint256 price;
}
```

* `seller`: Address of the NFT seller
* `paymentToken`: Address of the token to be used for payment (0x0 for ETH)
* `price`: Price of the NFT in the specified payment token

### State Variables

#### listings

```solidity
mapping(address => mapping(uint256 => Listing)) public listings;
```

A nested mapping that stores NFT listings. The first key is the NFT contract address, the second key is the token ID, and the value is the `Listing` struct.

### Functions

#### listNFT

```solidity
function listNFT(
    address nftContract,
    uint256 tokenId,
    address paymentToken,
    uint256 price
) external
```

Lists an NFT for sale.

**Parameters:**

* `nftContract`: Address of the NFT contract
* `tokenId`: ID of the NFT
* `paymentToken`: Address of the token to be used for payment (0x0 for ETH)
* `price`: Price of the NFT in the specified payment token

**Functionality:**

1. Transfers the NFT from the seller to the contract
2. Creates a new `Listing` and stores it in the `listings` mapping
3. Emits an `NFTListed` event

**Security Considerations:**

* Ensure that the contract has approval to transfer the NFT before calling this function

#### buyNFT

```solidity
function buyNFT(address nftContract, uint256 tokenId) external payable
```

Allows a user to purchase a listed NFT.

**Parameters:**

* `nftContract`: Address of the NFT contract
* `tokenId`: ID of the NFT

**Functionality:**

1. Retrieves the listing information
2. Handles payment in ETH or ERC-20 tokens
3. Transfers the NFT to the buyer
4. Deletes the listing
5. Emits an `NFTSold` event

**Security Considerations:**

* Checks if the NFT is listed for sale
* Ensures sufficient payment is sent for ETH transactions
* Uses the `transferFrom` function for ERC-20 payments, requiring prior approval

#### delistNFT

```solidity
function delistNFT(address nftContract, uint256 tokenId) external
```

Allows the seller to remove their NFT from the marketplace.

**Parameters:**

* `nftContract`: Address of the NFT contract
* `tokenId`: ID of the NFT

**Functionality:**

1. Verifies that the caller is the seller
2. Transfers the NFT back to the seller
3. Deletes the listing
4. Emits an `NFTDelisted` event

**Security Considerations:**

* Only the original seller can delist the NFT

#### withdrawETH

```solidity
function withdrawETH(uint256 amount) external onlyOwner
```

Allows the contract owner to withdraw ETH from the contract.

**Parameters:**

* `amount`: Amount of ETH to withdraw

**Security Considerations:**

* Only the contract owner can call this function
* Checks if the contract has sufficient balance before withdrawal

#### withdrawERC20

```solidity
function withdrawERC20(address token, uint256 amount) external onlyOwner
```

Allows the contract owner to withdraw ERC-20 tokens from the contract.

**Parameters:**

* `token`: Address of the ERC-20 token
* `amount`: Amount of tokens to withdraw

**Security Considerations:**

* Only the contract owner can call this function
* Assumes the contract has sufficient token balance

### Events

The contract emits the following events:

* `NFTListed`: When an NFT is listed for sale
* `NFTSold`: When an NFT is sold
* `NFTDelisted`: When an NFT is delisted

### Usage Examples

#### Listing an NFT for sale

```solidity
// Assume 'nftContract' is the address of your NFT contract
// and 'tokenId' is the ID of your NFT

// First, approve the marketplace contract to transfer your NFT
IERC721(nftContract).approve(marketplaceAddress, tokenId);

// Then, list the NFT for sale
marketplaceContract.listNFT(nftContract, tokenId, address(0), 1 ether);
```

#### Buying an NFT with ETH

```solidity
// Assume 'nftContract' and 'tokenId' identify the NFT you want to buy

// Send ETH with the transaction
marketplaceContract.buyNFT{value: 1 ether}(nftContract, tokenId);
```

#### Buying an NFT with an ERC-20 token

```solidity
// Assume 'nftContract' and 'tokenId' identify the NFT you want to buy
// and 'erc20TokenAddress' is the address of the payment token

// First, approve the marketplace contract to spend your tokens
IERC20(erc20TokenAddress).approve(marketplaceAddress, 1000);

// Then, buy the NFT
marketplaceContract.buyNFT(nftContract, tokenId);
```

### Security Considerations

1. **Reentrancy**: The contract uses the "checks-effects-interactions" pattern to prevent reentrancy attacks.
2. **Access Control**: The `Ownable` contract is used to restrict access to sensitive functions.
3. **Input Validation**: The contract checks for valid inputs and sufficient payments.
4. **Token Approvals**: Users must approve the contract to transfer their NFTs and ERC-20 tokens before listing or buying.
5. **ETH Handling**: The contract uses `transfer` for sending ETH, which has a gas stipend and can fail silently.

### Gas Optimization

1. The contract uses `delete` to remove listings, which can save gas by clearing storage.
2. It uses `_msgSender()` instead of `msg.sender`, which is more flexible for potential future upgrades.

### Best Practices

1. The contract follows the Checks-Effects-Interactions pattern for better security.
2. It uses OpenZeppelin's `Ownable` contract for standardized ownership management.
3. The contract emits events for important state changes, allowing for off-chain tracking.
4. It supports both ETH and ERC-20 token payments, increasing flexibility for users.

### Potential Improvements

1. Implement a fee system for the marketplace.
2. Add functionality to update listing prices.
3. Implement batch listing and buying functions for gas efficiency.
4. Add a mechanism to pause the contract in case of emergencies.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.phrase.trade/phrase.trade/contracts/phrase-trade-nft-marketplace.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
