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 杨辉三角|| 递推最通俗的理解就是数列,递推和数列的关系就好比 算法 和 数据结构 的关系,数列有点 像数据结构中的线性表(可以是顺序表&…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...
32位寻址与64位寻址
32位寻址与64位寻址 32位寻址是什么? 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元(地址),其核心含义与能力如下: 1. 核心定义 地址位宽:CPU或内存控制器用32位…...