Solidity中哈希函数的编码与解码

这篇具有很好参考价值的文章主要介绍了Solidity中哈希函数的编码与解码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

起因

写这篇文章的起因,是我在前端调试合约的时候,发现合约报错了,点开命令行报错,发现返回的是合约的 callData,我直接表演一个眼前一黑,我怎么直接的知道是调用哪个方法的时候报错呢? 于是有了这篇文章的探索

  • 目标: 如何根据 callData 解析出调用函数

  • 内容:从合约小白的角度,从哈希函数的前世今生开始讲起。如果你已经很了解这部分内容,可以直接划到底。
    -用到的库: ethers \ foundry

Solidity中哈希函数的编码与解码

哈希函数的前世今生

这一个部分直接引用 WTF 课程里对哈希函数的描述,讲解的很详细。 感谢社区的力量 github.com/AmazingAng/WTFSolidity


哈希函数(hash function)是一个密码学概念,它可以将任意长度的消息转换为一个固定长度的值,这个值也称作哈希(hash)。这一讲,我们简单介绍一下哈希函数及在solidity的应用

一个好的哈希函数应该具有以下几个特性

  • 单向性:从输入的消息到它的哈希的正向运算简单且唯一确定,而反过来非常难,只能靠暴力枚举。
  • 灵敏性:输入的消息改变一点对它的哈希改变很大。
  • 高效性:从输入的消息到哈希的运算高效。
  • 均一性:每个哈希值被取到的概率应该基本相等。
  • 抗碰撞性:
    • 弱抗碰撞性:给定一个消息x,找到另一个消息x'使得hash(x) = hash(x')是困难的。
    • 强抗碰撞性:找到任意xx',使得hash(x) = hash(x')是困难的。

Hash的应用

  • 生成数据唯一标识
  • 加密签名
  • 安全加密

Keccak256

Keccak256函数是solidity中最常用的哈希函数,用法非常简单:

哈希 = keccak256(数据);

Keccak256和sha3

这是一个很有趣的事情:

  1. sha3由keccak标准化而来,在很多场合下Keccak和SHA3是同义词,但在2015年8月SHA3最终完成标准化时,NIST调整了填充算法。所以SHA3就和keccak计算的结果不一样,这点在实际开发中要注意。
  2. 以太坊在开发的时候sha3还在标准化中,所以采用了keccak,所以Ethereum和Solidity智能合约代码中的SHA3是指Keccak256,而不是标准的NIST-SHA3,为了避免混淆,直接在合约代码中写成Keccak256是最清晰的。

生成函数哈希

介绍完定义,我们回归到文章主题,第一步,如何把 balanceOf(address) => 0x70a08231

  • ethers库里提供了两种方式
  1. ethers.utils.id('balanceOf(address)') 可以看到输入一个 text, 会返回一个 KECCAK256 的哈希
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6OiB8Te-1683731069929)(Img/img_2.png)]

  2. 先将 String 转换成 Utf8Bytes 的格式,然后再用 keccak256 哈希加密. 这里要注意不能直接 ethers.utils.keccak256(balanceOf(address)) 这种方式会报错,keccak256 只支持 DataHexstring 格式的转换

    Solidity中哈希函数的编码与解码

const textToUtf8Bytes = ethers.utils.toUtf8Bytes('balanceOf(address)')
const hashResult = ethers.utils.keccak256(textToUtf8Bytes)
  1. 补充上面 textToUtf8Bytes 可以用 ethers.utils.toUtf8String 反解出 String

输出如下,除开 0x 的前四个bytes 70a08231 为我们要的目标函数的哈希:

Solidity中哈希函数的编码与解码

反解哈希函数

上面我们获得了函数的哈希,那么现在到第二步,如何把 0x70a08231 => balanceOf(address)

  • 反解也是两种方式 (可能不全,我目前只知道这两个办法)
  • 第一种: bytes4_signature 可以理解为一个巨大的 Text Signature 🆚 Bytes Signature 的数据库,里面会定时去扫链上的合约,并将他们对应的 哈希值 与 方法名 存下来。能满足我们大多数开发的需求
  • 第二种,用命令行解密。
    • Step1: instal foundry
    • Step2: cast 4b 70a08231

Solidity中哈希函数的编码与解码

补充知识:前端仔会在哪里用到哈希函数?

答: EIP-165 规范文章

pragma solidity ^0.4.20;

interface ERC165 {
    /// @notice 查询一个合约时候实现了一个接口
    /// @param interfaceID  参数:接口ID, 参考上面的定义
    /// @return true 如果函数实现了 interfaceID (interfaceID 不为 0xffffffff )返回true, 否则为 false
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

EIP-165 中 提议了标准化接口的概念,并标准化了接口标识。 这么说可能有些抽象。 翻译一下就是我们可以通过调用这个方法,知道该合约是否支持某个接口。 比如 对于 一个 ERC-721 标准的 NFT 来说, 我怎么知道他是否兼容支持 ERC-2981 呢 ?

  • 首先明确 ERC-2981 对于 ERC-721 多了哪些能力?
    • 可以为 NFT 设置版税, 新增了 royaltyInfo(uint256,uint256) 查询方法
    • 那么我们就可以写下面这么一个函数,来判断 NFT 的 Fee
    • 因为 function 定义了 supportsInterface 需要传入一个 bytes4 类型的数据,所以我们传入 0x2a55205a, 对应 royaltyInfo(uint256,uint256)。 如果返回 true, 则说明 这个 NFT 兼容了 ERC-2981 标准,我们可以查看它对应的版税费率。
export const checkNftFeeAndGetFee = async ({ address, signer, tokenId }) => {
  const abi = ["function supportsInterface(bytes4) public view returns(bool)"];
  const checkContract = await createContract(address, abi, signer);
  const isSupportErc2981 = await checkContract.supportsInterface(0x2a55205a);
  let fee = 0;
  if (isSupportErc2981) {
    const nftContract = await createContract(address, erc2981ABI, signer);
    const result = await nftContract.royaltyInfo(
      tokenId,
      "100000000000000000000" // 100 * 10 ** 18, 因为要算费率,直接按100块钱算,返回多少就是对应的费率,比如 1 就是 1% 费率,
    );
    fee = Number(result?.royaltyAmount) / 10 ** 18;
  } else {
    fee = 0;
  }
  return fee.toString();
};

结尾

文章及代码demo同步发布在 我的github仓库 欢迎 star / fork /…, 互相交流学习文章来源地址https://www.toymoban.com/news/detail-457779.html

到了这里,关于Solidity中哈希函数的编码与解码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linux高并发web服务器开发(web服务器)18_函数解析http请求, 正则表达式,sscanf使用,http中数据特殊字符编码解码

    pdf详情版 编写函数解析http请求 ○ GET /hello.html HTTP/1.1rn ○ 将上述字符串分为三部分解析出来 编写函数根据文件后缀,返回对应的文件类型 sscanf - 读取格式化的字符串中的数据 ○ 使用正则表达式拆分 ○ [^ ]的用法 通过浏览器请求目录数据 ○ 读指定目录内容  opendir 

    2024年02月16日
    浏览(45)
  • Solidity编码规范

    避免使用 小写的L,大写的I,大写的O 应该避免在命名中单独出现,因为很容易产生混淆。 合约、库、事件、枚举及结构体命名——大驼峰 合约、库、事件及结构体命名应该使用单词首字母大写的方式。 比如:SimpleToken, SmartBank, CertificateHashRepository,Player。 函数、参数、

    2024年01月19日
    浏览(48)
  • opensl学习——base16编码解码、base64编码解码、ASCII码表、扩展ASCII码

    ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它等同于国际标准 ISO/IEC 646。 ASCII 编码于 1967 年第一次发布,最后一次更新是在 1986 年,迄今为止共收录了 128 个字符,包

    2024年02月07日
    浏览(37)
  • Solidity之abi.encode各编码方法使用

    什么是智能合约 ABI ABI = Specification for encoding and decoding 非常精炼的一句话:一套用来编码和解码的规范。  注意与合约字节码(bytecode)要区分开,字节码只是一串用十六进制数表示的 EVM 操作码。 在 Solidity 文档中描述为:   “ABI 是与以太坊生态系统中的合约交互的标准方

    2023年04月13日
    浏览(29)
  • URL在线编码/解码工具

    一刀工具箱提供在线URL编码解码工具:对网址Url进行UrlEncode编码转换,UrlEncode编码,UrlDecode解码。  代码片段 URL在线编码/解码工具 - 一刀工具箱APP 一刀工具箱提供在线URL编码解码工具:对网址Url进行UrlEncode编码转换,UrlEncode编码,UrlDecode解码。 https://tools.yidaotool.com/encode

    2024年02月11日
    浏览(37)
  • 解码器 | 基于 Transformers 的编码器-解码器模型

    基于 transformer 的编码器-解码器模型是 表征学习 和 模型架构 这两个领域多年研究成果的结晶。本文简要介绍了神经编码器-解码器模型的历史,更多背景知识,建议读者阅读由 Sebastion Ruder 撰写的这篇精彩 博文。此外,建议读者对 自注意力 (self-attention) 架构 有一个基本了解

    2024年02月08日
    浏览(40)
  • Unicode编码解码的全面介绍

    1. Unicode的起源和发展 Unicode是一个国际标准,旨在统一世界上所有文字的表示方式。它最初由Unicode协会创立,解决了不同字符集之间的兼容性问题。Unicode的发展经历了多个版本,每个版本都增加了新的字符和特性,以适应不断增长的全球化需求。 Unicode编码解码 | 一个覆盖广

    2024年04月08日
    浏览(26)
  • 什么是视频的编码和解码

    这段描述中,视频解码能力和视频编码能力指的是不同的处理过程。视频解码是将压缩过的视频数据解开并还原为可播放的视频流,而视频编码是将原始视频数据压缩成更小的尺寸,以减少存储空间和传输带宽。在这个上下文中,解码能力和编码能力的区别如下: 视频解码能

    2024年02月13日
    浏览(24)
  • 图片的编码存储与解码输出(基于Android将图片转Base64编码后再次解码会导致图片失真的解决办法)

    链接:https://pan.baidu.com/s/1hvVupGcCf1f41fizF08SNg?pwd=9988  提取码:9988 部分源码: 转Base64编码部分: 以上Android程序运行后会将图片的转为Base64编码进行存储,以下是图片转码后的结果。 下面是进行验证的php代码: 但是解码后输出后的照片出现了严重失真 数据量增加:Base64 编码

    2024年01月18日
    浏览(44)
  • 编码器 | 基于 Transformers 的编码器-解码器模型

    基于 transformer 的编码器-解码器模型是 表征学习 和 模型架构 这两个领域多年研究成果的结晶。本文简要介绍了神经编码器-解码器模型的历史,更多背景知识,建议读者阅读由 Sebastion Ruder 撰写的这篇精彩 博文。此外,建议读者对 自注意力 (self-attention) 架构 有一个基本了解

    2024年02月08日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包