【从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.rhkb.cn/news/141094.html

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

相关文章

ChatGPT的问世给哪些行业带来了冲击?

目录 引言Chat GPT 对行业的影响在线客服和智能客服行业传统自动回复机器人的局限性Chat GPT 的提升能力 教育培训行业个性化学习需求的挑战Chat GPT 的个性化优势 金融保险行业客户服务的变革Chat GPT 的智能化应用 医疗健康领域自助诊断及咨询的便利性Chat GPT 在医疗领域的应…

vue项目打包部署到服务器,报错。

这个是因为后端部署服务器时,名称没有对上,不是前端的问题,后端配置名称和前端的包名称保持一致就可以了。

轻量级c语言开源日志库log.c介绍 - 实现不同级别和参数化日志打印

前言 c语言没有现成的日志库,如果要记录日志,需要自己封装一个日志库。如果要实现日志级别和参数打印,还是比较麻烦的,正好在github找到了一个c语言开源日志库,可以实现日志级别打印,参数打印,…

SAP PO运维(四):适配器消息监控

登录SAP PO系统,点击“Configuration and Monitoring Home”,使用PISUPER账号登录: 2、选择“适配器引擎->消息监控器”: 3、查看是否有报错消息: 双击报错的数字,筛选出报错的条目(可以根据状态、接口命名空间等来筛选):常见的报错消息有: 接口配置问题:字段为空值…

好题记录 Leetcode 394.字符串解码 中等难度

方法一&#xff1a;递归 思路很简单&#xff0c;比较好理解&#xff0c;注意细节处理&#xff01;&#xff01;&#xff01; class Solution { public:string decodeString(string s) {string ans;for(int i0;s[i]!0;i){if(s[i]>a&&s[i]<z)anss[i];if(s[i]>…

十四、流式编程(4)

本章概要 终端操作 数组循环集合组合匹配查找信息数字流信息 终端操作 以下操作将会获取流的最终结果。至此我们无法再继续往后传递流。可以说&#xff0c;终端操作&#xff08;Terminal Operations&#xff09;总是我们在流管道中所做的最后一件事。 数组 toArray()&…

实时更新进度条:JavaScript中的定时器和异步编程技巧

前言 在Web开发中&#xff0c;有许多场景需要实时地更新页面上的进度&#xff0c;例如上传文件、数据处理等。本文将介绍如何利用JavaScript中的定时器和异步编程技巧来实现实时更新进度&#xff0c;并探讨一些其他解决方案。 处理进度实时更新&#xff1a; 利用异步编程实现实…

速卖通商品详情数据接口

速卖通商品详情数据接口&#xff08;aliexpress商品详情API接口&#xff09;可以获取到速卖通商品的详细信息&#xff0c;如商品标题、价格、库存、详情描述、图片等。 速卖通商品详情API接口是速卖通提供的一种产品数据接口&#xff0c;可以帮助速卖通卖家快速地将产品分类、…

Mysql主从数据恢复随笔

目录 1.使用pt-table-checksum插件安装方式如下 2.在主节点执行检查数据同步情况 3.同步检查出现的问题 3.1没有sock文件 3.2 Authentication plugin ‘sha256_password’ cannot be loaded: /usr/lib64/mysql/plugin/sha256_password.so: 无法打开共享对象文件: 没有那个文…

【刷题笔记9.24】LeetCode:二叉树最大深度

LeetCode&#xff1a;二叉树最大深度 1、题目描述&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 二、思路与算法 如果我们知道了左子树和右子树的最大深度 lll 和 rrr&#xff0c;…

基于Spring Boot的IT技术交流和分享平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 我国科学技术的不断发展&#xff0c;计算机的应用日渐成熟&#xff0c;其强大的功能给人们留下深刻的印象&#xff0c;它已经应用到了人类社会的各个层次的领域&#x…

MongoDB索引

索引支持在MongoDB中高效执行查询。如果没有索引&#xff0c;MongoDB必须扫描集合中的每个文档才能返回查询结果。如果查询存在适当的索引&#xff0c;MongoDB将使用该索引来限制它必须扫描的文档数。 尽管索引提高了查询性能&#xff0c;但添加索引对写入操作的性能有负面影响…

怎么去营造地中海风格?进来来看看吧

什么是地中海风格&#xff1f; 地中海风格是一种受地中海沿岸住宅建筑和美学影响的装饰风格。西班牙、希腊和摩洛哥等国的文化对地中海风格产生了影响。 简约是地中海生活的主要部分。地中海气候宜人&#xff0c;人们的生活态度闲适&#xff0c;这一点在色彩、设计、材料和图案…

2023第十二届中国智能产业高峰论坛之文档大模型的探索与思考

文章目录 前言合合信息多模态大模型与文档图像智能理解文档图像分析识别与理解的技术难题文档图像分析与预处理文档解析与识别版面分析与还原文档信息抽取与理解AI安全知识化&存储检索和管理 文档图像的分析识别与理解和大模型的关系文档图像大模型的进展LayoutLMUDOPDonut…

东郊到家app小程序公众号软件开发预约同城服务系统成品源码部署

东郊到家app系统开发&#xff0c;东郊到家软件定制开发&#xff0c;东郊到家小程序APP开发&#xff0c;东郊到家源码定制开发&#xff0c;东郊到家模式系统定制开发 一、上门软件介绍 1、上门app是一家以推拿为主项&#xff0c;个人定制型的o2o平台&#xff0c;上门app平台提…

次时代摸鱼骚操作:人在办公室轻松观看家里电脑上的4k电影(移动端公网访问本地群辉存储视频文件)

如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f; 文章目录 如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f;1.使用环境要求&#xff1a;2.下载群晖videostation&#xff1a;3.公网访问本地群晖videostation中的电影&#xff1a;4.公网条件下使用电脑…

详解MySQL索引+面试题

前言: 📕作者简介:热爱编程的小七,致力于C、Java、Python等多编程语言,热爱编程和长板的运动少年! 📘相关专栏Java基础语法,JavaEE初阶,数据库,数据结构和算法系列等,大家有兴趣的可以看一看。 😇😇😇有兴趣的话关注博主一起学习,一起进步吧! 一、索引概述…

购物新时尚RFID自助结账

购物已经变得更加简单和方便了&#xff0c;归功于RFID自助结账。别再排队等收银员了&#xff0c;让我们来看看这个酷炫的新方式。 RFID是什么&#xff1f;RFID就是那些小电子标签&#xff0c;它们能够让物品自动被识别。每个商品都有一个这样的标签&#xff0c;而RFID读卡器就…

【Linux is not Unix】Linux前言

目录 二战军工的产物——第一台现代电子数字计算机ENIAC&#xff08;埃尼阿克&#xff09; Unix Linux Linux企业应用现状 如今计算机已经应用在我们生活的各个层面&#xff0c;像我们日常使用的笔记本是计算机的一类&#xff0c;可以解决我们生活中遇到的很多问题&#xff…

视频监控系统/视频汇聚平台EasyCVR有下级平台注册时出现断流情况该如何排查解决?

视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等&#xff0c;视频智能分析平台EasyCVR融合性强、开放度…