【从0学习Solidity】52. EIP712 类型化数据签名

【从0学习Solidity】 52. EIP712 类型化数据签名

在这里插入图片描述

  • 博主简介:不写代码没饭吃,一名全栈领域的创作者,专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构,分享一些项目实战经验以及前沿技术的见解。
  • 关注我们的主页,探索全栈开发,期待与您一起在移动开发的世界中,不断进步和创造!
  • 本文收录于 不写代码没饭吃 的学习汇报系列,大家有兴趣的可以看一看。
  • 欢迎访问我们的微信公众号:不写代码没饭吃,获取更多精彩内容、实用技巧、行业资讯等。您关注的是我们前进的动力!

这一讲,我们介绍一种更先进、安全的签名方法,EIP712 类型化数据签名。

EIP712

之前我们介绍了 EIP191 签名标准(personal sign) ,它可以给一段消息签名。但是它过于简单,当签名数据比较复杂时,用户只能看到一串十六进制字符串(数据的哈希),无法核实签名内容是否与预期相符。

52-1.png

EIP712类型化数据签名是一种更高级、更安全的签名方法。当支持 EIP712 的 Dapp 请求签名时,钱包会展示签名消息的原始数据,用户可以在验证数据符合预期之后签名。

52-2.png

EIP712 使用方法

EIP712 的应用一般包含链下签名(前端或脚本)和链上验证(合约)两部分,下面我们用一个简单的例子 EIP712Storage 来介绍 EIP712 的使用方法。EIP712Storage 合约有一个状态变量 number,需要验证 EIP712 签名才可以更改。

链下签名

  1. EIP712 签名必须包含一个 EIP712Domain 部分,它包含了合约的 name,version(一般约定为 “1”),chainId,和 verifyingContract(验证签名的合约地址)。

    EIP712Domain: [{ name: "name", type: "string" },{ name: "version", type: "string" },{ name: "chainId", type: "uint256" },{ name: "verifyingContract", type: "address" },
    ]
    

    这些信息会在用户签名时显示,并确保只有特定链的特定合约才能验证签名。你需要在脚本中传入相应参数。

    const domain = {name: "EIP712Storage",version: "1",chainId: "1",verifyingContract: "0xf8e81D47203A594245E36C48e151709F0C19fBe8",
    };
    
  2. 你需要根据使用场景自定义一个签名的数据类型,他要与合约匹配。在 EIP712Storage 例子中,我们定义了一个 Storage 类型,它有两个成员: address 类型的 spender,指定了可以修改变量的调用者;uint256 类型的 number,指定了变量修改后的值。

    const types = {Storage: [{ name: "spender", type: "address" },{ name: "number", type: "uint256" },],
    };
    
  3. 创建一个 message 变量,传入要被签名的类型化数据。

    const message = {spender: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",number: "100",
    };
    

52-3.png

  1. 调用钱包对象的 signTypedData() 方法,传入前面步骤中的 domaintypes,和 message 变量进行签名(这里使用 ethersjs v6)。

    // 获得provider
    const provider = new ethers.BrowserProvider(window.ethereum)
    // 获得signer后调用signTypedData方法进行eip712签名
    const signature = await signer.signTypedData(domain, types, message);
    console.log("Signature:", signature);
    

52-4.png

链上验证

接下来就是 EIP712Storage 合约部分,它需要验证签名,如果通过,则修改 number 状态变量。它有 5 个状态变量。

  1. EIP712DOMAIN_TYPEHASH: EIP712Domain 的类型哈希,为常量。
  2. STORAGE_TYPEHASH: Storage 的类型哈希,为常量。
  3. DOMAIN_SEPARATOR: 这是混合在签名中的每个域 (Dapp) 的唯一值,由 EIP712DOMAIN_TYPEHASH 以及 EIP712Domain (name, version, chainId, verifyingContract)组成,在 constructor() 中初始化。
  4. number: 合约中存储值的状态变量,可以被 permitStore() 方法修改。
  5. owner: 合约所有者,在 constructor() 中初始化,在 permitStore() 方法中验证签名的有效性。

另外,EIP712Storage 合约有 3 个函数。

  1. 构造函数: 初始化 DOMAIN_SEPARATORowner
  2. retrieve(): 读取 number 的值。
  3. permitStore: 验证 EIP712 签名,并修改 number 的值。首先,它先将签名拆解为 r, s, v。然后用 DOMAIN_SEPARATOR, STORAGE_TYPEHASH, 调用者地址,和输入的 _num 参数拼出签名的消息文本 digest。最后利用 ECDSArecover() 方法恢复出签名者地址,如果签名有效,则更新 number 的值。
// SPDX-License-Identifier: MIT
// By 0xAA 
pragma solidity ^0.8.0;import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";contract EIP712Storage {using ECDSA for bytes32;bytes32 private constant EIP712DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");bytes32 private constant STORAGE_TYPEHASH = keccak256("Storage(address spender,uint256 number)");bytes32 private DOMAIN_SEPARATOR;uint256 number;address owner;constructor(){DOMAIN_SEPARATOR = keccak256(abi.encode(EIP712DOMAIN_TYPEHASH, // type hashkeccak256(bytes("EIP712Storage")), // namekeccak256(bytes("1")), // versionblock.chainid, // chain idaddress(this) // contract address));owner = msg.sender;}/*** @dev Store value in variable*/function permitStore(uint256 _num, bytes memory _signature) public {// 检查签名长度,65是标准r,s,v签名的长度require(_signature.length == 65, "invalid signature length");bytes32 r;bytes32 s;uint8 v;// 目前只能用assembly (内联汇编)来从签名中获得r,s,v的值assembly {/*前32 bytes存储签名的长度 (动态数组存储规则)add(sig, 32) = sig的指针 + 32等效为略过signature的前32 bytesmload(p) 载入从内存地址p起始的接下来32 bytes数据*/// 读取长度数据后的32 bytesr := mload(add(_signature, 0x20))// 读取之后的32 bytess := mload(add(_signature, 0x40))// 读取最后一个bytev := byte(0, mload(add(_signature, 0x60)))}// 获取签名消息hashbytes32 digest = keccak256(abi.encodePacked("\x19\x01",DOMAIN_SEPARATOR,keccak256(abi.encode(STORAGE_TYPEHASH, msg.sender, _num)))); address signer = digest.recover(v, r, s); // 恢复签名者require(signer == owner, "EIP712Storage: Invalid signature"); // 检查签名// 修改状态变量number = _num;}/*** @dev Return value * @return value of 'number'*/function retrieve() public view returns (uint256){return number;}    
}

Remix 复现

  1. 部署 EIP712Storage 合约。

  2. 运行 eip712storage.html,将 Contract Address 改为部署的 EIP712Storage 合约地址,然后依次点击 Connect MetamaskSign Permit 按钮签名。签名要使用部署合约的钱包,比如 Remix 测试钱包:

    public_key: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
    private_key: 503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb
    
  3. 调用合约的 permitStore() 方法,输入相应的 _num 和签名,修改 number 的值。

  4. 调用合约的 retrieve() 方法,看到 number 的值已经改变。

总结

这一讲,我们介绍了 EIP712 类型化数据签名,一种更先进、安全的签名标准。在请求签名时,钱包会展示签名消息的原始数据,用户可以在验证数据后签名。该标准应用广泛,在 Metamask,Uniswap 代币对,DAI 稳定币等场景均有使用,希望大家好好掌握。

在这里插入图片描述

如果这份博客对大家有帮助,希望各位给作者一个免费的点赞👍作为鼓励,并评论收藏一下⭐,谢谢大家!!!
制作不易,如果大家有什么疑问或给作者的意见,欢迎评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/87541.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

配电室电力监控系统:实时掌握电力运行状况

配电室是电力系统的重要组成部分,负责将发电厂输送的电力分配到各个用电终端。随着电力需求的不断增长,配电室的规模和复杂性也在增加。为了确保电力系统的稳定运行,采用配电室电力监控系统变得至关重要。 一、配电室电力监控系统概述 力…

TCP 和 UDP哪个更好

传输控制协议 (TCP) 和用户数据报协议 (UDP) 是互联网的基础支柱,支持从网络源到目的地的不同类型的数据传输。TCP更可靠,而UDP优先考虑速度和效率。本文解释了两种协议的工作原理,并详细讨论了…

【遥遥领先】Eolink IDEA 插件:零代码入侵,自动生成接口

省流版: Eolink 有 IDEA 插件吗? 有,而且遥遥领先!我们在一年半之前就发布了,而且功能更丰富! IDEA 插件市场搜索“Eolink Apikit”即可安装使用。 🚀使用指引:Eolink - IntelliJ ID…

virtualbox无界面打开linux虚拟机的bat脚本,以及idea(代替Xshell)连接linux虚拟机的方法

virtualbox无界面打开linux虚拟机的bat脚本,以及idea连接linux虚拟机的方法 命令行运行代码成功运行的效果图 idea连接linux虚拟机的方法【重要】查看虚拟机的IP地址idea中选择菜单(该功能可代替Xshell软件)配置设置连接成功进入idea中的命令…

Java on Azure Tooling 8月更新|以应用程序为中心的视图支持及 Azure 应用服务部署状态改进

作者:Jialuo Gan - Program Manager, Developer Division at Microsoft 排版:Alan Wang 大家好,欢迎阅读 Java on Azure 工具的八月更新。在本次更新中,我们将推出新的以应用程序为中心的视图支持,帮助开发人员在一个项…

德大黄鱼开捕 年产量20万吨 京东超市多举措保障黄鱼品质

作为“中国大黄鱼之都”,宁德大黄鱼占全国大黄鱼总产值产量均在90%以上。有关方面预计,今年全年宁德大黄鱼产量达20万吨,年增产10%,直接经济产值超百亿元。 宁德大黄鱼开捕活动,由宁德市政府、宁德渔业协会、京东超市…

leetCode 968.监控二叉树(利用状态转移+贪心)

968. 监控二叉树 - 力扣(LeetCode) 给定一个二叉树,我们在树的节点上安装摄像头。节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。计算监控树的所有节点所需的最小摄像头数量。 >>解题思路: 重要线索->题目示例中的摄…

不甘于被强势厂商捆绑,中国移动未来或自研5G基站

一直以来运营商被认为只是做服务,而设备等都是由设备商提供的,甚至由于如今的设备高度复杂,设备商已承包越来越多的基站运维工作,运营商的技术水平越来越低,不过随着中国移动发布5G射频芯片8676,似乎显示出…

JVM之选择合适的垃圾收集器(CMS、G1)

1.JVM内存模型,栈、本地方法栈、程序计数器、堆、元空间、方法区、本地方法区,除程序计数器外,其他区域都能进行垃圾收集 2.栈,它的生命周期与线程相同,线程私有,会使用操作系统原生内存,方法…

python过滤敏感词

敏感词一般是指带有敏感政治倾向(或反执政党倾向)、暴力倾向、不健康色彩的词或不文明用语,论坛、网站管理员一般会设定一些敏感词,以防不当发言影响论坛、网站环境。若论坛、网站设置了敏感词,用户编辑的内容又含有敏…

Levels - UE5中的建模相关

一些日常的笔记; 可以使用Shapes面板建立基础模型: 可以在PolyModel中继续细分模型: UE5中的建模有PolyGroups概念,可以在Attributes面板中直接编辑: 使用GrpPnt方式可以直接用笔刷设定新的PolyGroups,这样…

抖音SEO矩阵系统源码开发搭建

1. 确定需求和功能:明确系统的主要目标和需要实现的功能,包括关键词研究、短视频制作、外链建设、数据分析、账号设置优化等方面。 2. 设计系统架构:根据需求和功能确定系统的架构,包括前端、后端、数据库等部分的设计&#xff0…

计算机组成原理之硬件的内部结构,拆开单独的硬件,查看硬件组成部分的结构和功能。

大家好,欢迎阅读《计算机组成原理》的系列文章,本系列文章主要教内容是从零学习计算机组成原理,内容通俗易懂,大家好好学习吧!!! 更多的优质内容,请点击以下链接查看哦~~ ↓ ↓ ↓ …

由于找不到msvcr110.dll 无法继续执行的解决方法分享(最新)

msvcp110.dll 是 Microsoft Visual C 2010 Redistributable Package 中的一个组件,它包含了一些运行时库文件。当计算机缺少这个文件时,可能会出现一些问题,如程序无法正常运行、系统不稳定等。下面是 6 种修复方法: 第1种方法&am…

【注射论文基因,那些年不为人知的AI工具】

我们都知道写论文有很多前期准备工作&#xff0c;例如<任务书>、<文献综述>等等&#xff0c;那么我们能够用什么工具最大限度的提高完成效率的同时还能保证质量呢&#xff0c;让我们接着往下看&#x1f447; 1.文献快速阅读-iTextMaster 文章主题确定了&#xff0…

向建筑人推荐中国建筑出版传媒的《乡村振兴战略下传统村落文化旅游设计》

向建筑人推荐中国建筑出版传媒的《乡村振兴战略下传统村落文化旅游设计》

mysql第二次作业

作业&#xff1a; 创建一个数据&#xff0c;db_classics 创建一张表&#xff1a;t_hero id name nickname age address job weapon group 1 张百川 玉皇大帝 200000 2 孙悟空 齐天大圣 3 林妹妹 创建数据库&#xff0c;创建英雄表 添加对应…

Docker Dockerfile解析

Dockerfile是什么 Dockerfile是用来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 官网&#xff1a;Dockerfile reference | Docker Docs 构建三步骤&#xff1a; 编写Dockerfile文件docker build命令构建镜像docker run依镜像运行容…

基于微信小程的流浪动物救助宠物领养平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

四川天蝶电子商务有限公司可靠吗?真实吗?

​近年来&#xff0c;抖音带货已成为一种日益流行的新零售趋势。而四川天蝶电子商务有限公司作为抖音带货领域的先行者之一&#xff0c;备受消费者关注。但是&#xff0c;我们不能仅凭其名声来评判其可靠性。在对该公司的抖音带货服务进行评估之前&#xff0c;有必要了解和了解…