首页 > 解决方案 > 如何使用智能合约在以太坊区块链上存储 IPFS 哈希?

问题描述

我正在开发一个 react + IPFS DAPP 并制作一个简单的宠物店应用程序。现在我刚刚在 remix 上创建智能合约并尝试它的功能正常工作,但我遇到了一个问题。

交易到 PetShop.generatePet 错误:错误编码参数:错误:无效的数组化值(argument="value",value="QmWmyoMoctfbAaiEs2G46gpeUmhqFRDW6KWo64y5r581Vz",code=INVALID_ARGUMENT,version=bytes/5.0.5)

每当我调用 generatePet 函数并传递 IPFS 哈希时,它都会返回上述错误。

合同宠物店

pragma solidity ^0.6.6;

import "https://github.com/MuhammadSajid404/ERC721-Token/blob/master/ERC721.sol";

contract PetShop is ERC721 {
    
      uint256 public tokenId;
      uint256 public prevOwnerTokenID;
      
      mapping(uint256 => uint256) public priceMapping;
      mapping(uint256 => bytes32) tokenIdToOffchainContentHash;
      
      event PetGenerated(address, uint256, uint256, bytes32);
      event BuyPet(uint256, address, address);
      event SuccessfulEtherWithdrawal(uint256, address, bool);
      
       constructor() public
        ERC721("ShanBuilders", "SBRS")
        {}
     
       function generatePet(uint256 _petPrice, bytes32 contentHash) public returns(bool) {
         
         require(msg.sender != address(0), "Please! Check back! Registeration should not be from zero address");
         require(msg.sender == ownerA, "Only contract owner can generate more pets");
         
         tokenId++;
         require(tokenId <= 16, "More than 16 pets is not allowed");
         
         priceMapping[tokenId] = _petPrice;
         tokenIdToOffchainContentHash[tokenId] = contentHash;
         _mint(ownerA, tokenId);
         emit PetGenerated(ownerA, tokenId, _petPrice, contentHash);
         return true;
       }
       
       function checkPrice(uint256 _tokenId) public view returns(uint256) {
           return priceMapping[_tokenId];
       }
       
       function checkHashForAToken(uint256 _tokenId) public view returns(bytes32) {
           return tokenIdToOffchainContentHash[_tokenId];
       }
       
       function buyPet(uint256 _tokenId) public payable returns(bool, string memory) {
           
           prevOwnerTokenID = _tokenId;
           address buyer = msg.sender;
           address _owner = ownerOf(prevOwnerTokenID);
           
           require(buyer != address(0), "Should not be zero address");
           require(_exists(prevOwnerTokenID), "Invalid property Id, not registered");
           require(msg.value == checkPrice(prevOwnerTokenID), "Please Send The Required Value");
           
           withDraw(msg.value);
            _transfer(_owner, buyer, prevOwnerTokenID);
           emit BuyPet(_tokenId, _owner, buyer);
           return (true, "Succesful");
       }
       
       function withDraw(uint256 _amount) public returns(bool) {
       
        address _owner = ownerOf(prevOwnerTokenID);
        require(_amount > 0, "Amount must be valid");
        
        payable(_owner).transfer(_amount);
        emit SuccessfulEtherWithdrawal(_amount, _owner, true);
        return true;
    }
     
}

注意:我更喜欢使用字节而不是字符串,因为它们消耗的气体比字符串少。如何解决这个问题,我在 stackoverflow 上看到了很多答案,但实际上我没有理解其中的任何一个。

标签: ethereumsolidityipfs

解决方案


bytes32对于 SHA-256 散列来说已经足够了,对于其他散列函数或可变长度的多散列格式可能还不够。

请参阅https://ethereum.stackexchange.com/questions/6861/what-datatype-should-i-use-for-an-ipfs-address-hash


推荐阅读