NFT,全称为非同质化代币(Non-Fungible Token),是一种基于区块链技术的数字资产。与比特币等传统加密货币不同,NFT是唯一的、不可替代的,每一个NFT都有其独特的标识信息。

1. 基本概念

  1. 非同质化:传统的加密货币如比特币是同质化的,即每一个比特币都是相同且可以互换的。而NFT是独一无二的,每个NFT都有独特的属性和价值,无法与其他NFT互换。
  2. 区块链技术:NFT通常建立在以太坊(Ethereum)等支持智能合约的区块链平台上。区块链确保了NFT的透明性、不可篡改性和安全性。

2. 特点

  1. 独特性:每个NFT都有独特的标识符,能够在区块链上唯一标识。
  2. 不可分割性:大多数NFT是不可分割的,即不能像比特币一样分割成更小的单位。
  3. 所有权:NFT的所有权记录在区块链上,可以被验证和追踪。
  4. 稀缺性:创作者可以通过限制发行量来确保NFT的稀缺性,从而增加其价值。

3. 应用领域

  1. 艺术品:数字艺术品是NFT最早也是最广泛的应用之一。艺术家可以通过发行NFT来销售他们的数字作品,保证作品的独特性和所有权。
  2. 收藏品:NFT也被广泛应用于数字收藏品,如虚拟卡牌、游戏道具等。这些数字收藏品通过NFT的形式确保其唯一性和可验证性。
  3. 虚拟房地产:在虚拟世界(如Decentraland和Cryptovoxels)中,用户可以购买、出售和交易虚拟土地,这些土地通常以NFT的形式存在。
  4. 音乐和视频:音乐家和视频创作者也开始通过NFT销售他们的作品,确保版权和收益分配的透明性。
  5. 门票和证书:NFT可以用来发行独特的数字门票或证书,确保其真实性和不可篡改性。

4. 优势

  1. 防伪:NFT可以验证数字资产的真实性和所有权,防止伪造和欺诈。
  2. 透明性:所有交易和所有权变更都记录在区块链上,任何人都可以查看和验证。
  3. 去中心化:无需第三方中介,交易可以直接在区块链上进行。

5. 实现示例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

// 定义 IERC165 接口,用于接口检测
interface IERC165 {
    function supportsInterface(bytes4 interfaceID) external pure returns (bool);
}

// 定义 ERC721 标准接口,继承自 IERC165 接口
interface IERC721 is IERC165 {
    function balanceOf(address owner) external view returns (uint256 balance);

    function ownerOf(uint256 tokenId) external view returns (address owner);

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    function approve(address to, uint256 tokenId) external;

    function getApproved(uint256 tokenId)
        external
        view
        returns (address operator);

    function setApprovalForAll(address operator, bool approved) external;

    function isApprovedForAll(address owner, address operator)
        external
        view
        returns (bool);
}

// 实现 ERC721 合约,继承自 IERC721 接口
contract ERC721 is IERC721 {
    // 定义事件,用于跟踪代币转移和授权操作
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    // map from token id to owner
    mapping(uint256 => address) _ownerOf;

    // map owner address to token count
    mapping(address => uint256) _balanceOf;

    // map token id to approved address
    mapping(uint256 => address) _approvals;

    // map from owner to operator approvals
    mapping(address => mapping(address => bool)) public isApprovedForAll;

    // 检查合约是否实现了某个接口
    function supportsInterface(bytes4 interfaceID)
        external
        pure
        returns (bool)
    {
        return
            interfaceID == type(IERC721).interfaceId ||
            interfaceID == type(IERC165).interfaceId;
    }

    // 查询 token ID 的所有者
    function ownerOf(uint256 tokenId) external view returns (address owner) {
        owner = _ownerOf[tokenId];
        require(owner != address(0), "token id doesn`t exist");
    }

    // 查询某个地址的持有 token 数量
    function balanceOf(address owner) external view returns (uint256) {
        require(owner != address(0), "owner address == address(0)");
        return _balanceOf[owner];
    }

    // 设置或取消对某个操作员的全权操作授权
    function setApprovalForAll(address operator, bool approved) external {
        isApprovedForAll[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    // 批准某个地址可以转移指定的 token
    function approve(address spender, uint256 id) external {
        address owner = _ownerOf[id];
        require(
            msg.sender == owner || isApprovedForAll[owner][msg.sender],
            "not authorized"
        );

        _approvals[id] = spender;

        emit Approval(owner, spender, id);
    }

    // 查询某个 token 被批准的地址
    function getApproved(uint256 id) external view returns (address) {
        require(_ownerOf[id] != address(0), "token doesn't exist");
        return _approvals[id];
    }

    // 内部函数,验证地址是否被批准或为所有者
    function _isApprovedOrOwner(
        address owner,
        address spender,
        uint256 id
    ) internal view returns (bool) {
        return (spender == owner ||
            isApprovedForAll[owner][spender] ||
            spender == _approvals[id]);
    }

    // 转移 token,从一个地址到另一个地址
    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public {
        require(from == _ownerOf[id], "from != owner");
        require(to != address(0), "transfer to zero address");

        require(_isApprovedOrOwner(from, msg.sender, id), "not authorized");

        _balanceOf[from]--;
        _balanceOf[to]++;
        _ownerOf[id] = to;

        delete _approvals[id];

        emit Transfer(from, to, id);
    }

    // 安全转移 token,从一个地址到另一个地址
    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) external {
        transferFrom(from, to, id);
    }

    // 内部函数,用于铸造新的 token
    function _mint(address to, uint256 id) internal {
        require(to != address(0), "mint to zero address");
        require(_ownerOf[id] == address(0), "already minted");

        _balanceOf[to]++;
        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    // 内部函数,用于销毁已存在的 token
    function _burn(uint256 id) internal {
        address owner = _ownerOf[id];
        require(owner != address(0), "not minted");

        _balanceOf[owner] -= 1;

        delete _ownerOf[id];
        delete _approvals[id];

        emit Transfer(owner, address(0), id);
    }
}

// 示例合约,继承自 ERC721
contract ERC721Example is ERC721 {
    // 铸造新的 token
    function mint(uint256 id) external {
        _mint(msg.sender, id);
    }

    // 销毁指定 token
    function burn(uint256 id) external {
        _burn(id);
    }
}

孟斯特

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意

腾讯云开发者社区:孟斯特