在智能合约中使用_hashtypeddatav4和_signtypeddata(Etherjs)在前端不起作用

发布于 2025-01-19 05:30:02 字数 1819 浏览 3 评论 0原文

我正在尝试使用_signtypeddata(Etherjs)在前端进行编码NFT数据,如下

 const domain = {
    name: "og-nft",
    version: "1",
  };
  const types = {
    Nft: [
      { name: "URI", type: "string" },
      { name: "price", type: "uint256" },
    ],
  };

  // The data to sign
  const [voucher, setVoucher] = useState({
    URI: "",
    price: '1',
  });
const signature = await signer._signTypedData(domain, types, voucher);

所述 _ signpeddata in docs

我在蒙古签名和签名数据库,我已经在Hardhat上部署了智能合约,并且通过使用ECDSA.Recover凝视签名签名者来验证签名的真实性,

function verifyVoucher(NFTVoucher calldata voucher, bytes memory signature)
        public
        view
        returns (address)
    {
        require(voucher.price > 0, "Price must be greater than 0");
      //  require(voucher.tokenId > 0, "Token ID must be greater than 0");
        bytes32 hash = _hash(voucher);
        //string memory hash="";
        return ECDSA.recover(hash, signature);
    }

但结果与实际签名者不匹配。我认为我在上面使用的哈希功能中犯了一些错误。

0xe8c795f9168269940b31a470ad82e89a453e88b9 signer
0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 owner

以下是哈希函数。

function _hash(NFTVoucher calldata voucher)
        internal
        view
        returns (bytes32)
    {
        return
            _hashTypedDataV4(
                keccak256(
                    abi.encode(
                        keccak256(
                            "Nft(string URI,uint256 price)"
                        ),
                        keccak256(bytes(voucher.URI)),
                        voucher.price
                    )
                )
            );
    }

引用上述

i am trying to encode the nft data using _signTypedData(etherjs) in frontend as follows

 const domain = {
    name: "og-nft",
    version: "1",
  };
  const types = {
    Nft: [
      { name: "URI", type: "string" },
      { name: "price", type: "uint256" },
    ],
  };

  // The data to sign
  const [voucher, setVoucher] = useState({
    URI: "",
    price: '1',
  });
const signature = await signer._signTypedData(domain, types, voucher);

reference to above
_signTypedData in docs

I am storing the voucher and signature in the mongo database, I have deployed smart contract on hardhat and I am verifying the authenticity of signature by peering out the signer of the voucher using ECDSA.recover

function verifyVoucher(NFTVoucher calldata voucher, bytes memory signature)
        public
        view
        returns (address)
    {
        require(voucher.price > 0, "Price must be greater than 0");
      //  require(voucher.tokenId > 0, "Token ID must be greater than 0");
        bytes32 hash = _hash(voucher);
        //string memory hash="";
        return ECDSA.recover(hash, signature);
    }

but the result of this is not matching with actual signer. i think I am making some mistake in the hash function above used.

0xe8c795f9168269940b31a470ad82e89a453e88b9 signer
0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 owner

below is the hash function.

function _hash(NFTVoucher calldata voucher)
        internal
        view
        returns (bytes32)
    {
        return
            _hashTypedDataV4(
                keccak256(
                    abi.encode(
                        keccak256(
                            "Nft(string URI,uint256 price)"
                        ),
                        keccak256(bytes(voucher.URI)),
                        voucher.price
                    )
                )
            );
    }

reference to above _hashTypedDataV4

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

感情废物 2025-01-26 05:30:02

这是erc20permit的例子,希望对你有帮助

function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {
    require(deadline >= block.timestamp, "ERC20Permit: expired deadline");
        
    bytes32 hashStruct = keccak256(
        abi.encode(
            keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
            owner,
            spender,
            amount,
            nonce[owner],
            deadline
        )
    );

    bytes32 hash = keccak256(
        abi.encodePacked(
            '\x19\x01',
            keccak256(abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
            keccak256(bytes(name_)),
            keccak256(bytes(version())),
            chainId,
            address(this)
        ),
            hashStruct
        )
    );
    
   
    address signer = ecrecover(hash, v, r, s);
    require(
        signer != address(0) && signer == owner,
        "ERC20Permit: invalid signature"
    );
    nonces[owner]++;
    _approve(owner, spender, amount);
}

this is erc20permit example,I hope it can help you

function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {
    require(deadline >= block.timestamp, "ERC20Permit: expired deadline");
        
    bytes32 hashStruct = keccak256(
        abi.encode(
            keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
            owner,
            spender,
            amount,
            nonce[owner],
            deadline
        )
    );

    bytes32 hash = keccak256(
        abi.encodePacked(
            '\x19\x01',
            keccak256(abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
            keccak256(bytes(name_)),
            keccak256(bytes(version())),
            chainId,
            address(this)
        ),
            hashStruct
        )
    );
    
   
    address signer = ecrecover(hash, v, r, s);
    require(
        signer != address(0) && signer == owner,
        "ERC20Permit: invalid signature"
    );
    nonces[owner]++;
    _approve(owner, spender, amount);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文