golang验证Etherscan上的智能合约
文章目录
- golang验证Etherscan上的智能合约
- 为什么要验证智能合约
- 如何使用golang去验证合约
- 获取EtherscanAPI密钥
- Verify Source Code接口
- Check Source Code Verification Status接口
- 演示示例及注意事项
- 网络问题无法调用Etherscan接口(最重要的步骤)
golang验证Etherscan上的智能合约
在阅读此文章前,您需要掌握一定的基础知识,如golang与以太坊交互,此篇文章是对其的补充,提供利用代码自动验证智能合约,减少不太必要的人工操作,如果由于Etherscan接口的更新,导致代码不适用,请随时与我联系。
为什么要验证智能合约
出于多种原因,您可能希望在公共区块浏览器上开源(验证)您的智能合约。
在Etherscan或其他类似的区块链浏览器上验证智能合约具有以下几个重要的用途:
- 透明度和信任:通过验证智能合约,你向社区展示了你的合约代码是公开的、可审查的。这增加了用户和其他开发者对你项目的信任,因为他们可以查看代码,确认合约行为的逻辑和功能。
- 安全性审查:验证后的智能合约会吸引更多人的关注,特别是智能合约专家和安全研究人员。他们可以帮助发现潜在的安全漏洞或问题,并提供改进建议。这有助于提升你的合约的安全性和可靠性。
- 抵抗黑客攻击:通过让更多人审查你的合约代码,可以提前发现和修复可能存在的漏洞,从而降低黑客攻击的风险。黑客往往会寻找未经审查或有漏洞的智能合约来进行攻击,而经过验证的合约能够减少这种风险。
- 开发者社区增长:开源并验证的智能合约能够鼓励更多开发者参与到你的项目中来。他们可以基于你的代码进行二次开发、添加新功能或者将你的合约作为基础构建新的应用程序,从而推动生态系统的发展和扩展。
总结来说,通过在Etherscan上验证智能合约,你不仅增加了透明度和安全性,还能吸引更多开发者和用户参与到你的区块链项目中来,推动项目的发展和采纳。
如何使用golang去验证合约
如果你是通过在线工具如Remix或OpenZeppelin的合约向导部署了你的合约,请考虑使用合约验证页面进行验证。Verify & Publish Contract Source Code | Etherscan
如果你是通过开发工具如Hardhat、Foundry、Truffle等部署了你的合约,请考虑使用插件来自动化验证过程。Contract Verification Plugins | Etherscan
如果你是一名使用golang去开发Web3应用的开发者或学习者,我们可以查看Etherscan提供的api接口,然后根据需要,自己造轮子。Contracts | Etherscan
这里我们找到验证合约所必要的两个api接口,Verify Source Code和Check Source Code Verification Status,意如其名,一个是将合约源代码提交给类似 Etherscan 的浏览器进行验证,一个是返回合同验证请求的成功或错误状态。
只要这两个接口都返回成功,我们的智能合约就已经在Etherscan上进行了验证。
获取EtherscanAPI密钥
注册登录->仪表盘->API-KEYs->Add->copy,具体请看链接Getting an API key | Etherscan。
Verify Source Code接口
将合约源代码提交给类似 Etherscan 的浏览器进行验证。
根据官方提供的api接口详情,我们可以造出以下的代码,但是略有不同,上面表单中没有提供OptimizationUsed这个参数(0没有,1有),但是我在使用postman测试的时候,得到必须添加这个参数的结果,此外,这个接口必须使用POST请求,尽管它更像是GET请求,没有Body,只有Params。
package utilsimport ("encoding/json""fmt""io""math/big""net/http""net/url""reflect"
)type VerifyRequest struct {ApiKey string `json:"apiKey"` // API密钥ChainId *big.Int `json:"chainId"` // 链IDCodeFormat string `json:"codeformat"` // 代码格式SourceCode string `json:"sourceCode"` // 合约源代码ConstructorArguments string `json:"constructorArguements,omitempty"` // 构造函数参数ContractAddress string `json:"contractaddress"` // 合约地址ContractName string `json:"contractname"` // 合约名称CompilerVersion string `json:"compilerversion"` // 编译器版本OptimizationUsed int `json:"OptimizationUsed"` // 是否使用了优化
}type VerifyResponse struct {Status string `json:"status"` // 状态Message string `json:"message"` // 详细信息Result string `json:"result"` // 具体结果
}func Verify(apiKey string, chainId *big.Int, codeFormat, sourceCode, constructorArgs, contractAddress, contractName, compilerVersion string, optimizationUsed int) error {// 构造请求数据requestData := VerifyRequest{ApiKey: apiKey,ChainId: chainId,CodeFormat: codeFormat,SourceCode: sourceCode,ConstructorArguments: constructorArgs,ContractAddress: contractAddress,ContractName: contractName,CompilerVersion: compilerVersion,OptimizationUsed: optimizationUsed,}// 创建一个 Client 实例client := &http.Client{}// 准备查询参数params := url.Values{}// 使用反射获取requestData结构体中的字段和值val := reflect.ValueOf(requestData)// 如果是指针类型,则获取其指向的值if val.Kind() == reflect.Ptr {val = val.Elem()}for i := 0; i < val.NumField(); i++ {field := val.Type().Field(i)value := val.Field(i).Interface()// 获取标签的值tag := field.Tag.Get("json")if tag == "" {// 如果没有标签,默认使用字段名tag = field.Name}// 将字段名和值添加到查询参数中params.Set(tag, fmt.Sprint(value))}// 构建POST请求的URLapiURL := "https://api.etherscan.io/api?module=contract&action=verifysourcecode&" + params.Encode()// 创建POST请求req, err := http.NewRequest("POST", apiURL, nil)if err != nil {return fmt.Errorf("创建POST请求失败:%v", err)}// 发送POST请求到Etherscan APIresp, err := client.Do(req)if err != nil {return fmt.Errorf("POST请求失败:%v", err)}defer resp.Body.Close()// 读取响应体body, err := io.ReadAll(resp.Body)if err != nil {return fmt.Errorf("读取响应体失败:%v", err)}// 解析JSON响应var verifyResponse VerifyResponseerr = json.Unmarshal(body, &verifyResponse)if err != nil {return fmt.Errorf("解析JSON响应失败:%v", err)}// 检查验证提交状态if verifyResponse.Status != "1" {return fmt.Errorf("验证提交失败:%s,%s\n", verifyResponse.Message, verifyResponse.Result)}fmt.Printf("验证提交成功:%s,%s\n", verifyResponse.Message, verifyResponse.Result)return nil
}
其实在这里,也可以把verifyResponse.Result返回出去,因为接下来的检查验证会用到它。总之根据自己所需,可以随意更改函数形式,代码的灵活性和趣味性不尽也如此了吧。
参数列表:
参数 | 类型 | 描述 | 举例 |
---|---|---|---|
apiKey | string | Etherscan的Api密钥,注册账户免费获取 | ********************************** |
chainId | *big.Int | 提交验证的链,例如主网1 | big.NewInt(int64(11155111)) |
codeFormat | string | 单个文件,使用solidity-single-file 、使用JSON文件solidity-standard-json-input | solidity-single-file |
sourceCode | string | Solidity 源代码 | // SPDX-License-Identifier…… |
constructorArgs | string | 可选,如果合约使用构造函数参数,则包括 | nil |
contractAddress | string | 您的合约部署地址 | 0x**************************************** |
contractName | string | 合同的名称,例如contracts/Verified.sol:Verified | Verified |
compilerVersion | string | 使用的编译器版本,例如v0.8.26+commit.8a97fa7a | v0.8.26+commit.8a97fa7a |
optimizationUsed | int | 是否使用了优化,否0 ,是1 | 0 |
补充:
获取solc编译器版本:打开cmd,输入
solc --version
Check Source Code Verification Status接口
返回合同验证请求的成功或错误状态。
这个接口相对于上一个,就好写很多,只是简单的一个GET请求,我们很容易地写出以下代码。
package utilsimport ("encoding/json""fmt""io""net/http"
)type CheckVerificationStatusRequest struct {ApiKey string `json:"apiKey"` // API密钥Guid string `json:"guid"` // 从验证请求收到的唯一值
}type CheckVerificationStatusResponse struct {Status string `json:"status"` // 状态Message string `json:"message"` // 详细信息Result string `json:"result"` // 具体结果
}func CheckVerificationStatus(apiKey, guid string) error {requestData := CheckVerificationStatusRequest{ApiKey: apiKey,Guid: guid,}// 创建一个 Client 实例client := &http.Client{}// 构建GET请求的URLapiURL := "https://api.etherscan.io/api?module=contract&action=checkverifystatus&guid=" + requestData.Guid + "&apikey=" + requestData.ApiKey// 创建GET请求req, err := http.NewRequest("GET", apiURL, nil)if err != nil {return fmt.Errorf("创建GET请求失败:%v", err)}// 发送GET请求到Etherscan APIresp, err := client.Do(req)if err != nil {return fmt.Errorf("GET请求失败:%v", err)}defer resp.Body.Close()// 读取响应体body, err := io.ReadAll(resp.Body)if err != nil {return fmt.Errorf("读取响应体失败:%v", err)}// 解析JSON响应var checkVerificationStatusResponse CheckVerificationStatusResponseerr = json.Unmarshal(body, &checkVerificationStatusResponse)if err != nil {return fmt.Errorf("解析JSON响应失败:%v", err)}// 检查验证状态if checkVerificationStatusResponse.Status != "1" {return fmt.Errorf("验证失败:%s,%s\n", checkVerificationStatusResponse.Message, checkVerificationStatusResponse.Result)}fmt.Printf("验证成功:%s,%s\n", checkVerificationStatusResponse.Message, checkVerificationStatusResponse.Result)return nil
}
通过这个函数,我们可以查询我们提交的验证是否已经通过了。
参数列表:
参数 | 类型 | 描述 | 举例 |
---|---|---|---|
apiKey | string | Etherscan的Api密钥,注册账户免费获取 | ********************************** |
guid | string | 从验证请求收到的唯一值guid | pdresyk3uidtwtcn5qxp3gqyp4ifsughl9hr8xdt3t2iw7acug |
演示示例及注意事项
然后我用我在上一篇博客,也就是文章最开始的链接中的这个样例合约(已经部署在Sepolia上,但未进行验证),进行演示。
下面是调用Verify()函数的过程,(注意,因为网络问题,所以我对这个函数进行了小小的修改,所以叫VerifyZh()函数,后面会进行说明的),然后我们得到返回的guid标识。
接着,下面是调用CheckVerificationStatus()函数的过程,(注意,因为网络问题,所以我对这个函数进行了小小的修改,所以叫CheckVerificationStatusZh()函数,后面会进行说明的),然后我们看到我们的验证已经完成了!
当然也有可能失败,因为验证是需要排队的,等待一段时间,再次查询就好了。
然后打开Etherscan,查看我们的合约,可以看到它的Contract上多了一个√,我们点击后,就可以看到我们合约的源代码以及其他信息了。
注意
无法验证合约,有很多原因,请根据报错信息自行摸索,或者在下方留言。
此外Etherscan很聪明,如果别人已经验证过一个合约,然后你部署了跟他一模一样的字节码,就可能导致你部署的合约不用验证,就已经验证了。
网络问题无法调用Etherscan接口(最重要的步骤)
打开魔法软件面板,点击设置,查看代理端口。
或者,打开windows设置,点击网络和Internet->代理->手动设置代理服务器->编辑,查看端口。
然后将之前的代码中的如下代码
// 创建一个 Client 实例client := &http.Client{}
替换为(注意端口号!!!)
// 创建一个自定义的 Transport 实例transport := &http.Transport{Proxy: func(req *http.Request) (*url.URL, error) {return url.Parse("http://127.0.0.1:7897") // 设置代理(注意端口号!!!)},}// 创建一个自定义的 Client 实例client := &http.Client{Transport: transport, // 设置 Transport}
就可以了,我的加了Zh的函数就是修改了这段代码。
上述方法适用于大部分因网络问题,无法调用第三方api接口的问题。
这篇文章到这里就结束了,希望对您有所帮助,欢迎点赞、评论加收藏,您的支持是对我最大的帮助!
相关文章:

golang验证Etherscan上的智能合约
文章目录 golang验证Etherscan上的智能合约为什么要验证智能合约如何使用golang去验证合约获取EtherscanAPI密钥Verify Source Code接口Check Source Code Verification Status接口演示示例及注意事项网络问题无法调用Etherscan接口(最重要的步骤) golan…...

Visual Studio编译优化选项
目录 /O1 和 /O2 /Ox 内联函数 虚函数优化 代码重排 循环优化 链接时间优化 代码分割 数学优化 其他优化选项 在Visual Studio中,编译优化选项是用于提高程序性能的重要工具。编译器提供了多种优化级别和选项,可以根据不同的需要进行选择。 在…...

sql业务场景分析思路参考
1、时间可以进行排序,也可以用聚合函数对时间求最大值max(时间) 例如下面的例子:取最晚入职的人,那就是将入职时间倒序排序,然后limit 1 表: 场景:查找最晚入职员工的所有信息 se…...

Django权限系统如何使用?
Django的权限系统是一个强大而灵活的特性,允许你控制不同用户对应用程序中资源的访问。以下是使用Django权限系统的几个基本步骤: 1. 定义模型权限 在你的models.py文件中,你可以为每个模型定义自定义权限。这通过在模型的Meta类里设置perm…...

基于整体学习的大幅面超高分遥感影像桥梁目标检测(含数据集下载地址)
文章摘要 在遥感图像(RSIs)中进行桥梁检测在各种应用中起着至关重要的作用,但与其他对象检测相比,桥梁检测面临独特的挑战。在RSIs中,桥梁在空间尺度和纵横比方面表现出相当大的变化。因此,为了确保桥梁的…...

逻辑回归模型(非回归问题,而是解决二分类问题)
目录: 一、Sigmoid激活函数:二、逻辑回归介绍:三、决策边界四、逻辑回归模型训练过程:1.训练目标:2.梯度下降调整参数: 一、Sigmoid激活函数: Sigmoid函数是构建逻辑回归模型的重要激活函数&am…...

QT的OpenGL渲染窗QOpenGLWidget Class
Qt - QOpenGLWidget (class) (runebook.dev) 一、说明 QOpenGLWidget 类是用于渲染 OpenGL 图形的小部件。从Qt 5.4就开始退出,它对于OpenGL有专门的配合设计。 二、QOpenGLWidget类的成员 2.1 Public类函数 QOpenGLWidget(QWidget *parent nullptr,Qt…...

单元测试和集成测试
软件测试中,单元测试和集成测试是比较常见的方法 单元测试:这是一种专注于最小可测试单元(通常是函数或方法)的测试,用于验证单个组件的行为是否符合预期。它通常由开发者自己完成,可以尽早发现问题&#…...

【JAVA入门】Day15 - 接口
【JAVA入门】Day15 - 接口 文章目录 【JAVA入门】Day15 - 接口一、接口是对“行为”的抽象二、接口的定义和使用三、接口中成员的特点四、接口和类之间的关系五、接口中新增的方法5.1 JDK8开始接口中新增的方法5.1.1 接口中的默认方法5.1.2 接口中的静态方法 5.2 JDK9 开始接口…...

ES6 之 Set 与 Map 数据结构要点总结(一)
Set 数据结构 Set 对象允许你存储任何类型的唯一值,无论是原始值还是对象引用。 特性: 所有值都是唯一的,没有重复。值的顺序是根据添加的顺序确定的。可以使用迭代器遍历 Set。 常用方法: 1. add(value):添加一个新…...

一文学会用RKE部署高可用Kubernetes集群
k8s架构图 RKE简介 RKE全称Rancher Kubernetes Engine,是一个快速的,多功能的 Kubernetes 安装工具。通过RKE,我们可以快速的安装一个高可用K8S集群。RKE 支持多种操作系统,包括 MacOS、Linux 和 Windows。 K8S原生安装需要的先…...

数据加密的常见方法
数据加密是一门历史悠久的技术,它通过加密算法和加密密钥将明文(原始的或未加密的数据)转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文。这一技术的核心是密码学,它利用密码技术对信息进行加密,实现信息隐蔽&#…...

天童美语:推荐给孩子的人文历史纪录片
孩子们都有自己的偏好,有的孩子喜欢打游戏,有的孩子喜欢看剧看电影,有的孩子喜欢看书。针对不同的孩子我们要因材施教,所以,广州天童教育给大家推荐一下适合给孩子看的人文历史类的纪录片,让精美的画面&…...

数字人技术如何推动教育事业可持续创新发展?
数字人技术作为一种新兴的教育手段,无论是幼儿园还是大学课堂,数字人都可以融入于各阶段教育中,结合动作捕捉、AI等技术,提高教育资源的利用。 AI智能交互数字人应用: 数字人结合NLP自然语言处理技术以及AI大模型技术…...

FPGA程序设计
在设计FPGA时,多运用模块化的思想取设计模块,将某一功能设计成module。 设计之前要先画一下模块设计图,列出输入输出接口,再进一步设计内部功能。 状态机要画图,确定每个状态和状态之间怎么切换。状态用localparam定…...

彻底开源,免费商用,上海AI实验室把大模型门槛打下来
终于,业内迎来了首个全链条大模型开源体系。 大模型领域,有人探索前沿技术,有人在加速落地,也有人正在推动整个社区进步。 就在近日,AI 社区迎来首个统一的全链条贯穿的大模型开源体系。 虽然社区有LLaMA等影响力较大…...

MTEB评估基准使用指北
文章目录 介绍评估数据 介绍 文本嵌入通常是在单一任务的少量数据集上进行评估,这些数据集未涵盖其可能应用于其他任务的情况,不清楚在语义文本相似性(semantic textual similarity, STS)等任务上的最先进嵌入是否同样适用于聚类或…...

31. 1049. 最后一块石头的重量 II, 494.目标和,474.一和零
class Solution { public:int lastStoneWeightII(vector<int>& stones) {int sum 0;for(int stone : stones) sum stone;int bagSize sum /2;vector<int> dp(bagSize 1, 0);for(int i 0; i < stones.size(); i){ //遍历物品for(int j bagSize; j >…...

PDF 中图表的解析探究
PDF 中图表的解析探究 0. 引言1. 开源方案探究 0. 引言 一直以来,对文档中的图片和表格处理都非常有挑战性。这篇文章记录一下最近工作上在这块的探究。图表分为图片和表格,这篇文章主要记录了对表格的探究。还有,我个人主要做日本项目&…...

递推(C语言)
文章目录 1.斐波那契数列2.太波那契数列3.二维递推问题4.实战4.1 力扣509 斐波那契数4.2 力扣70 爬楼梯4.3 力扣119 杨辉三角|| 递推最通俗的理解就是数列,递推和数列的关系就好比 算法 和 数据结构 的关系,数列有点 像数据结构中的线性表(可以是顺序表&…...

安卓微信8.0之后如何利用缓存找回的三天之前不可见的朋友圈图片
安卓微信8.0之后如何利用缓存找回的三天之前不可见的朋友圈图片 复习了下安卓程序的知识,我们会了解到,安卓程序清楚数据的时候有两个选项 一个是清除全部数据一个是清除缓存。 清除全部数据表示清除应用数据缓存。 对于安卓微信8.0之后而言࿰…...

ES6 Class(类) 总结(九)
ES6 中的 class 是一种面向对象编程的语法糖,提供了一种简洁的方式来定义对象的结构和行为。 JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。 function Point(x, y) {this.x x;this.y y; } Point.prototype.toString fu…...

使用 Vue.js 和 Element Plus 实现自动完成搜索功能
使用 Vue.js 和 Element Plus 实现自动完成搜索功能 一、前言1.环境准备2.组件配置3.后端数据请求4.样式5.总结 一、前言 在前端开发中,实现自动完成(autocomplete)功能可以极大地提升用户体验,特别是在需要用户输入和选择内容的…...

SpringBoot自定义starter
SpringBoot自定义starter 1、SpringBoot之starter机制 1.1、什么是自定义starter SpringBoot中的starter是一种非常重要的机制(自动化配置),能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖&#…...

深入探索大语言模型
深入探索大语言模型 引言 大语言模型(LLM)是现代人工智能领域中最为重要的突破之一。这些模型在自然语言处理(NLP)任务中展示了惊人的能力,从文本生成到问答系统,无所不包。本文将从多个角度全面介绍大语…...

querylist多线程采集curlMulti时,报错Curl error(60)
前言 在使用querylist多线程采集的时候,报错: Curl error(60)。测试了下用http时没有问题,https时有问题。其原因在于多线程采集库引用的另一个库有问题。需要手动更改。 解决 找到:vendor/ares333/php-curl/src/Curl.php 文件,…...

Python数据分析~~美食排行榜
目录 1.模块的导入和路径的选择 2.访问前面五行数据 3.按照条件进行筛选 4.获取店铺评分里面的最高分 5.打印对应的店铺的名字 1.模块的导入和路径的选择 # 导入pandas模块,简称为pd import pandas as pd # 使用read_csv()函数 # TODO 读取路径"/Users/fe…...

Linux下解压.tar.gz文件
.tar.gz 是一种常用的压缩包格式,尤其在Unix、Linux以及macOS系统中非常普遍。这个格式结合了两种不同的功能: Tar (.tar): “Tar” 是“Tape Archive”的缩写,最初是为了将数据备份到磁带上而设计的。Tar命令可以将多个文件和目录打包成一个…...

【电商选品干货】差异化卖点要这样打造,80%商家却做不到
今天就给大家说说,如何去挖掘产品的差异化卖点?我们要找差异化卖点,就是因为我们的产品转化率不足,通常有下面几点原因: 1、产品差异化卖点不足,商家占比30% 2、流量和产品卖点不匹配,商家占比…...

LabVIEW比例压力控制阀自动测试系统
开发了一套基于LabVIEW编程和PLC控制的比例控制阀自动测试系统。该系统能够实现共轨管稳定的超高压供给,自动完成比例压力控制阀的耐久测试、流量滞环测试及压力-流量测试。该系统操作简便,具有高精度和高可靠性,完全满足企业对自动化测试的需…...