📜  合约 ERC721 solidity (1)

📅  最后修改于: 2023-12-03 15:22:57.769000             🧑  作者: Mango

合约 ERC721 Solidity

ERC721是一种代币标准,用于实现不同的数字资产的非同质化表示,例如土地、人物、宠物、信用点等。下面介绍如何使用Solidity编写ERC721合约。

定义合约
pragma solidity ^0.5.0;

contract ERC721 {
    string public name;
    string public symbol;

    constructor(string memory _name, string memory _symbol) public {
        name = _name;
        symbol = _symbol;
    }

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }
    uint256 private _totalSupply;

    function balanceOf(address _owner) public view returns (uint256) {
        return _balances[_owner];
    }
    mapping(address => uint256) private _balances;

    function ownerOf(uint256 _tokenId) public view returns (address) {
        require(_exists(_tokenId));
        return _tokenOwner[_tokenId];
    }
    mapping(uint256 => address) private _tokenOwner;

    function approve(address _approved, uint256 _tokenId) public {
        address owner = ownerOf(_tokenId);
        require(_approved != owner);
        require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
        _tokenApprovals[_tokenId] = _approved;
        emit Approval(owner, _approved, _tokenId);
    }
    mapping(uint256 => address) private _tokenApprovals;

    function getApproved(uint256 _tokenId) public view returns (address) {
        require(_exists(_tokenId));
        return _tokenApprovals[_tokenId];
    }

    function setApprovalForAll(address _operator, bool _approved) public {
        _operatorApprovals[msg.sender][_operator] = _approved;
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    function isApprovedForAll(address _owner, address _operator) public view returns (bool) {
        return _operatorApprovals[_owner][_operator];
    }

    function transferFrom(address _from, address _to, uint256 _tokenId) public {
        require(_isApprovedOrOwner(msg.sender, _tokenId));
        require(_from != address(0));
        require(_to != address(0));
        _transfer(_from, _to, _tokenId);
    }

    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public {
        transferFrom(_from, _to, _tokenId);
        require(_checkOnERC721Received(_from, _to, _tokenId, _data));
    }

    function safeTransferFrom(address _from, address _to, uint256 _tokenId) public {
        safeTransferFrom(_from, _to, _tokenId, "");
    }

    function _isApprovedOrOwner(address _spender, uint256 _tokenId) private view returns (bool) {
        address owner = ownerOf(_tokenId);
        return (_spender == owner || getApproved(_tokenId) == _spender || isApprovedForAll(owner, _spender));
    }

    function _transfer(address _from, address _to, uint256 _tokenId) private {
        require(ownerOf(_tokenId) == _from);
        require(_to != address(0));
        _balances[_from] -= 1;
        _balances[_to] += 1;
        _tokenOwner[_tokenId] = _to;
        emit Transfer(_from, _to, _tokenId);
    }

    function _checkOnERC721Received(address _from, address _to, uint256 _tokenId, bytes memory _data) private returns (bool) {
        if (!_to.isContract()) {
            return true;
        }
        bytes4 retval = IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
        return (retval == _ERC721_RECEIVED);
    }
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    function _exists(uint256 _tokenId) private view returns (bool) {
        address owner = _tokenOwner[_tokenId];
        return owner != address(0);
    }

    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);

}
继承ERC721合约
pragma solidity ^0.5.0;

import "./ERC721.sol";

contract MyERC721 is ERC721 {

  constructor() ERC721("My ERC721 Token", "M721") public {}

  function createToken(address _owner, uint256 _tokenId) public {
      // 创建一个新代币,所有权为_owner
      _mint(_owner, _tokenId);
  }

}

这个合约使用了import命令将ERC721合约引入到自己的代码中,然后创建合约MyERC721继承自ERC721合约,并在构造函数中设置代币名字和缩写名字。

创建代币
MyERC721 myNFT = new MyERC721();

myNFT.createToken(msg.sender, 1);

该代码创建了一个名为myNFT的实例,然后调用createToken函数创建一个代币,tokenId为1,所有权为调用该函数的地址msg.sender。

转移代币
myNFT.transferFrom(msg.sender, receiver, 1);

该代码将tokenId为1的代币从调用该函数的地址msg.sender转移到一个接收地址receiver。

以上是使用Solidity编写ERC721合约的介绍。