Wild NFT Images Documentation


1. Precautions for NFT transfers and marketplace sales

Warning for transfers to smart contracts: Do not transfer NFTs to a smart contract unless you are certain the contract can safely receive native currency without any other code execution. Transferring NFTs to a smart contract may result in permanent loss of NFT/funds when someone uses the force buy feature on your NFT.
Warning for NFT Marketplace sales: Do not put for sale on a marketplace an NFT with a price higher than the force buy price. That can result in a loss for the buyer as anyone can get the NFT with the force buy price later.

2. How Mint and ForceBuy Work

The detailed Solidity implementation of the mint and forceBuy functions can be found in Section 6.

Minting: When you mint an NFT, a mint price is paid in the chain's native currency (in addition to the gas fees required for the transaction). The mint price may vary across different chains. If an NFT is not already minted, it can be minted at any time. Note that the NFT image and metadata are available before minting, so you can view the NFT details beforehand.

ForceBuy: This functionality is exclusively for already minted NFTs. With ForceBuy, you can acquire an NFT directly by paying its current ForceBuy price. The ForceBuy price is calculated as MINT_PRICE * FORCE_BUY_FACTOR, where the FORCE_BUY_FACTOR is currently set to 2.

When a ForceBuy transaction is executed, the new owner pays the ForceBuy price (at least twice the mint price), and the previous owner automatically receives 70% of this amount. For example, if the ForceBuy price is 2x the mint price, the previous owner will receive 1.4x the mint price. After the transaction, a new ForceBuy price is set for the NFT, calculated as msg.value * FORCE_BUY_FACTOR. This means that subsequent ForceBuy transactions for the same NFT will require a payment at least 2x the previous ForceBuy price.

Self-ForceBuy: You can also use the ForceBuy functionality on an NFT that you already own. In this case, the ForceBuy price is updated, and 70% of the ForceBuy amount is returned to you in the same transaction. Effectively, this means you only pay 30% of the ForceBuy cost to increase the future ForceBuy price of your NFT.

3. Obtaining Testnet Tokens

To interact with the blockchain on various testnets, you'll need testnet tokens. Use the following faucets to obtain tokens:

4. Using MetaMask

To mint or force buy NFTs on blockchain, you must have a browser extension installed and configured, like MetaMask browser extension.

Note: Ensure MetaMask is connected to the appropriate network before interacting with the blockchain.

5. Adding or Updating RPC URLs in MetaMask

To add or update an RPC URL for a network in MetaMask, follow these steps:

  1. Open MetaMask and navigate to the network dropdown.
  2. Select Add Network or Custom RPC.
  3. Enter the RPC URL, chain ID, and other details. You can find these details on Chainlist.
  4. Save the configuration.

Or use the buttons from Chainlist that will add the network configuration automatically to MetaMask.

6. How Minting and Force Buying Works

Below are the Solidity code snippets for the mint and forceBuy functions:

Mint Function

function mint(uint256 tokenId) external payable {
    require(MINT_ENABLED, "Minting is not enabled");
    require(msg.value == MINT_PRICE, "Incorrect payment amount");
    require(tokenId >= MIN_TOKEN_ID && tokenId <= MAX_TOKEN_ID, "Token id not in range");
    require(_forceBuyPrices[tokenId] == 0, "Token Id already minted");

    _safeMint(msg.sender, tokenId);
    MINTED_NFTS = MINTED_NFTS + 1;
    lastTokenIdChanged = tokenId;
    lastTokenIdChangeTimestamp = block.timestamp;

    _forceBuyPrices[tokenId] = MINT_PRICE * FORCE_BUY_FACTOR;
    paymentAddress.transfer(msg.value);
    emit TokenActivity(msg.sender, tokenId, 1, msg.value);
}
            

Force Buy Function

function forceBuy(uint256 tokenId) external payable {
    require(FORCE_BUY_ENABLED, "Force buy is not enabled");
    require(_forceBuyPrices[tokenId] != 0, "Token Id not minted yet");

    uint256 requiredPrice = _forceBuyPrices[tokenId];
    require(msg.value >= requiredPrice, "Payment < min force buy price");
    require(msg.value < requiredPrice * FORCE_BUY_FACTOR, "Payment > max force buy price");

    address payable previousOwner = payable(ownerOf(tokenId));

    if (previousOwner != msg.sender) {
        _transfer(previousOwner, msg.sender, tokenId);
    }

    _forceBuyPrices[tokenId] = msg.value * FORCE_BUY_FACTOR;
    lastTokenIdChanged = tokenId;
    lastTokenIdChangeTimestamp = block.timestamp;

    uint256 ownerShare = (msg.value * FORCE_BUY_OWNER_SHARE) / 1000;
    uint256 paymentAddressShare = msg.value - ownerShare;

    paymentAddress.transfer(paymentAddressShare);
    bool sent = previousOwner.send(ownerShare);
    if (!sent){
        paymentAddress.transfer(ownerShare);
        emit SendFundsFailed(previousOwner, ownerShare);
    }
    emit TokenActivity(msg.sender, tokenId, 2, msg.value);
}