NFTFractionalizer

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "Fractionalizer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/*
 * Self-contained NFT Fractionalizer
 * - No external imports (works in Remix out of the box)
 * - Locks one ERC-721 in this contract
 * - Mints ERC-20 "fraction" tokens to the caller
 *
 * How to use:
 * 1) Deploy this contract.
 * 2) Approve this contract to move your NFT (in your ERC-721's approve(vault, tokenId)).
 * 3) Call fractionalize(nftAddress, tokenId, name, symbol, totalSupplyWith18Decimals).
 * 4) Distribute the ERC-20 fractions as you like.
 */

/* -------- Minimal ERC-721 interface we need -------- */
interface IERC721Minimal {
    function ownerOf(uint256 tokenId) external view returns (address);
    function transferFrom(address from, address to, uint256 tokenId) external;
}

/* -------- Minimal ERC-20 implementation -------- */
contract SimpleERC20 {
    string public name;
    string public symbol;
    uint8 public constant decimals = 18;

    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    constructor(string memory _name, string memory _symbol, uint256 _supply, address _to) {
        name = _name;
        symbol = _symbol;
        _mint(_to, _supply);
    }

    function approve(address spender, uint256 value) external returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function transfer(address to, uint256 value) external returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        uint256 allowed = allowance[from][msg.sender];
        require(allowed >= value, "ERC20: insufficient allowance");
        if (allowed != type(uint256).max) {
            allowance[from][msg.sender] = allowed - value;
        }
        _transfer(from, to, value);
        return true;
    }

    function _transfer(address from, address to, uint256 value) internal {
        require(to != address(0), "ERC20: transfer to zero");
        uint256 bal = balanceOf[from];
        require(bal >= value, "ERC20: balance too low");
        unchecked {
            balanceOf[from] = bal - value;
        }
        balanceOf[to] += value;
        emit Transfer(from, to, value);
    }

    function _mint(address to, uint256 value) internal {
        require(to != address(0), "ERC20: mint to zero");
        totalSupply += value;
        balanceOf[to] += value;
        emit Transfer(address(0), to, value);
    }
}

/* -------- Fractionalizer (Vault + ERC20) -------- */
contract NFTFractionalizer {
    address public nftAddress;
    uint256 public nftTokenId;
    address public fractions;        // ERC-20 token address
    bool public fractionalized;

    event Fractionalized(
        address indexed owner,
        address indexed nft,
        uint256 indexed tokenId,
        address fractionsToken,
        uint256 totalSupply
    );

    /**
     * @notice Locks the NFT and mints ERC-20 fractions to the caller.
     * @param _nft Address of the ERC-721 collection (your Manifold contract)
     * @param _tokenId Token ID to vault
     * @param _name Name for the fractions token (e.g., "Whalesink Fraction")
     * @param _symbol Symbol for the fractions token (e.g., "WHALE")
     * @param _totalSupply Total supply to mint, in wei units (e.g., 1_000_000 * 10**18)
     */
    function fractionalize(
        address _nft,
        uint256 _tokenId,
        string calldata _name,
        string calldata _symbol,
        uint256 _totalSupply
    ) external {
        require(!fractionalized, "Already fractionalized");

        IERC721Minimal nft = IERC721Minimal(_nft);
        require(nft.ownerOf(_tokenId) == msg.sender, "Not NFT owner");

        // Pull the NFT into this vault
        nft.transferFrom(msg.sender, address(this), _tokenId);

        // Mint ERC-20 fractions to the caller
        SimpleERC20 token = new SimpleERC20(_name, _symbol, _totalSupply, msg.sender);

        // Record state
        nftAddress = _nft;
        nftTokenId = _tokenId;
        fractions = address(token);
        fractionalized = true;

        emit Fractionalized(msg.sender, _nft, _tokenId, address(token), _totalSupply);
    }
}"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": []
  }
}}

Tags:
Factory|addr:0x7444b68a1f2fcabc5762e12014a0321992b72b6b|verified:true|block:23748707|tx:0xbf1aa0b9ab11ca758ba43c02c8444dd3a1a6ea890dd83f5f42d7736ad372557f|first_check:1762534628

Submitted on: 2025-11-07 17:57:09

Comments

Log in to comment.

No comments yet.