# Burn to Earn Tested OnChain Solidity code

```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyRefundableNFT is ERC721, Ownable {
    uint256 public tokenCounter;
    uint256 public refundPeriod; // in seconds (days will be converted to seconds)
    uint256 public refundPercentage; // e.g., 90 means 90% refund
    mapping(uint256 => uint256) public mintTimestamps; // stores the mint timestamp for each NFT
    mapping(uint256 => uint256) public mintPrices; // stores the mint price for each NFT

    constructor(uint256 _refundPeriodInDays, uint256 _refundPercentage) ERC721("MyRefundableNFT", "MNFT") {
        tokenCounter = 0;
        refundPeriod = _refundPeriodInDays * 1 days; // converting days to seconds
        refundPercentage = _refundPercentage;
    }

    // Function to mint new NFTs and hold funds for the refund period
    function mintNFT(address recipient) public payable onlyOwner returns (uint256) {
        require(refundPercentage >= 0 && refundPercentage <= 100, "Invalid refund percentage");

        uint256 newTokenId = tokenCounter;
        tokenCounter++;

        _safeMint(recipient, newTokenId);

        // Store the minting price and timestamp
        mintTimestamps[newTokenId] = block.timestamp;
        mintPrices[newTokenId] = msg.value;

        return newTokenId;
    }

    // Function to burn the NFT and refund the buyer if within refund period
    function burnNFT(uint256 tokenId) public {
        require(ownerOf(tokenId) == msg.sender, "Only the owner can burn this NFT");
        require(block.timestamp <= mintTimestamps[tokenId] + refundPeriod, "Refund period has expired");

        // Calculate refund amount
        uint256 refundAmount = (mintPrices[tokenId] * refundPercentage) / 100;

        // Burn the NFT
        _burn(tokenId);

        // Transfer the refund to the user
        payable(msg.sender).transfer(refundAmount);

        // Clean up data for the burned token
        delete mintTimestamps[tokenId];
        delete mintPrices[tokenId];
    }

    // Fallback function to receive funds
    receive() external payable {}

    // Function to withdraw contract funds by the owner (developer)
    function withdrawFunds() public onlyOwner {
        payable(owner()).transfer(address(this).balance);
    }
}

```

Got it! We will take an ERC-721 smart contract and modify it to include the following features:

1. **Developer inputs a duration in days (e.g., 3 days)**: Funds from minting will be held for this period.
2. **Developer inputs a refund percentage (e.g., 90%)**: A percentage of the mint price will be refunded if the buyer burns the NFT within the specified days.
3. **NFT Burn Functionality**: Buyers can burn their NFTs within the set time frame to receive the refund.

Here’s the Solidity smart contract code that incorporates these features:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyRefundableNFT is ERC721, Ownable {
    uint256 public tokenCounter;
    uint256 public refundPeriod; // in seconds (days will be converted to seconds)
    uint256 public refundPercentage; // e.g., 90 means 90% refund
    mapping(uint256 => uint256) public mintTimestamps; // stores the mint timestamp for each NFT
    mapping(uint256 => uint256) public mintPrices; // stores the mint price for each NFT

    constructor(uint256 _refundPeriodInDays, uint256 _refundPercentage) ERC721("MyRefundableNFT", "MNFT") {
        tokenCounter = 0;
        refundPeriod = _refundPeriodInDays * 1 days; // converting days to seconds
        refundPercentage = _refundPercentage;
    }

    // Function to mint new NFTs and hold funds for the refund period
    function mintNFT(address recipient) public payable onlyOwner returns (uint256) {
        require(refundPercentage >= 0 && refundPercentage <= 100, "Invalid refund percentage");

        uint256 newTokenId = tokenCounter;
        tokenCounter++;

        _safeMint(recipient, newTokenId);

        // Store the minting price and timestamp
        mintTimestamps[newTokenId] = block.timestamp;
        mintPrices[newTokenId] = msg.value;

        return newTokenId;
    }

    // Function to burn the NFT and refund the buyer if within refund period
    function burnNFT(uint256 tokenId) public {
        require(ownerOf(tokenId) == msg.sender, "Only the owner can burn this NFT");
        require(block.timestamp <= mintTimestamps[tokenId] + refundPeriod, "Refund period has expired");

        // Calculate refund amount
        uint256 refundAmount = (mintPrices[tokenId] * refundPercentage) / 100;

        // Burn the NFT
        _burn(tokenId);

        // Transfer the refund to the user
        payable(msg.sender).transfer(refundAmount);

        // Clean up data for the burned token
        delete mintTimestamps[tokenId];
        delete mintPrices[tokenId];
    }

    // Fallback function to receive funds
    receive() external payable {}

    // Function to withdraw contract funds by the owner (developer)
    function withdrawFunds() public onlyOwner {
        payable(owner()).transfer(address(this).balance);
    }
}
```

#### Key Features :

1. **Refund Period**: The developer inputs a number of days when deploying the contract, and this is converted into seconds for Solidity to track time accurately. For example, 3 days would be `3 * 24 * 60 * 60` seconds.
2. **Refund Percentage**: The developer also specifies the refund percentage when deploying the contract. This ensures that when an NFT is burned, the buyer can receive a refund based on the mint price and this percentage.
3. **Minting Process**:
   * When an NFT is minted, the mint price (the `msg.value` sent in the mint transaction) and the mint timestamp are stored for each token ID.
   * The funds from the mint transaction stay in the contract until withdrawn by the owner after the refund period has passed.
4. **Burning NFTs**:
   * The buyer can burn the NFT within the specified refund period.
   * If the NFT is burned within that period, the buyer gets refunded based on the percentage set by the developer.
5. **Funds Withdrawal**:
   * After the refund period expires, the contract owner (developer) can withdraw the remaining funds.

#### Example:

* The developer deploys the contract with a 3-day refund period and a 90% refund rate.
* A buyer mints an NFT by paying, e.g., 1 ETH. This amount is held in the contract.
* The buyer can burn the NFT within 3 days and receive 90% of the mint price (i.e., 0.9 ETH).
* After the 3 days, if the NFT is not burned, the developer can withdraw the remaining funds.

This contract gives the buyers a safe option to get their money back if they are not satisfied with the NFT within the given time, and developers can build trust by offering this refund mechanism.
