golang验证Etherscan上的智能合约

news2024/9/23 23:29:06

文章目录

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

golang验证Etherscan上的智能合约

在阅读此文章前,您需要掌握一定的基础知识,如golang与以太坊交互-CSDN博客,此篇文章是对其的补充,提供利用代码自动验证智能合约,减少不太必要的人工操作,如果由于Etherscan接口的更新,导致代码不适用,请随时与我联系。

为什么要验证智能合约

出于多种原因,您可能希望在公共区块浏览器上开源(验证)您的智能合约。

在Etherscan或其他类似的区块链浏览器上验证智能合约具有以下几个重要的用途:

  1. 透明度和信任:通过验证智能合约,你向社区展示了你的合约代码是公开的、可审查的。这增加了用户和其他开发者对你项目的信任,因为他们可以查看代码,确认合约行为的逻辑和功能。
  2. 安全性审查:验证后的智能合约会吸引更多人的关注,特别是智能合约专家和安全研究人员。他们可以帮助发现潜在的安全漏洞或问题,并提供改进建议。这有助于提升你的合约的安全性和可靠性。
  3. 抵抗黑客攻击:通过让更多人审查你的合约代码,可以提前发现和修复可能存在的漏洞,从而降低黑客攻击的风险。黑客往往会寻找未经审查或有漏洞的智能合约来进行攻击,而经过验证的合约能够减少这种风险。
  4. 开发者社区增长:开源并验证的智能合约能够鼓励更多开发者参与到你的项目中来。他们可以基于你的代码进行二次开发、添加新功能或者将你的合约作为基础构建新的应用程序,从而推动生态系统的发展和扩展。

总结来说,通过在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 utils

import (
	"encoding/json"
	"fmt"
	"io"
	"math/big"
	"net/http"
	"net/url"
	"reflect"
)

type VerifyRequest struct {
	ApiKey               string   `json:"apiKey"`                          // API密钥
	ChainId              *big.Int `json:"chainId"`                         // 链ID
	CodeFormat           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请求的URL
	apiURL := "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 API
	resp, 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 VerifyResponse
	err = 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返回出去,因为接下来的检查验证会用到它。总之根据自己所需,可以随意更改函数形式,代码的灵活性和趣味性不尽也如此了吧。

参数列表:

参数类型描述举例
apiKeystringEtherscan的Api密钥,注册账户免费获取**********************************
chainId*big.Int提交验证的,例如主网1big.NewInt(int64(11155111))
codeFormatstring单个文件,使用solidity-single-file、使用JSON文件solidity-standard-json-inputsolidity-single-file
sourceCodestringSolidity 源代码// SPDX-License-Identifier……
constructorArgsstring可选,如果合约使用构造函数参数,则包括nil
contractAddressstring您的合约部署地址0x****************************************
contractNamestring合同的名称,例如contracts/Verified.sol:VerifiedVerified
compilerVersionstring使用的编译器版本,例如v0.8.26+commit.8a97fa7av0.8.26+commit.8a97fa7a
optimizationUsedint是否使用了优化,否0,是10

补充:

获取solc编译器版本:打开cmd,输入

solc --version

在这里插入图片描述

Check Source Code Verification Status接口

返回合同验证请求的成功或错误状态。

在这里插入图片描述

在这里插入图片描述

这个接口相对于上一个,就好写很多,只是简单的一个GET请求,我们很容易地写出以下代码。

package utils

import (
	"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请求的URL
	apiURL := "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 API
	resp, 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 CheckVerificationStatusResponse
	err = 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
}

通过这个函数,我们可以查询我们提交的验证是否已经通过了。

参数列表:

参数类型描述举例
apiKeystringEtherscan的Api密钥,注册账户免费获取**********************************
guidstring从验证请求收到的唯一值guidpdresyk3uidtwtcn5qxp3gqyp4ifsughl9hr8xdt3t2iw7acug

演示示例及注意事项

然后我用我在上一篇博客,也就是文章最开始的链接中的这个样例合约(已经部署在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接口的问题。

这篇文章到这里就结束了,希望对您有所帮助,欢迎点赞、评论加收藏,您的支持是对我最大的帮助!

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

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

相关文章

应用层协议原理——因特网提供的运输服务

我们已经考虑了计算机网络能够一般性地提供的运输服务。现在我们要更为具体地考察由因特网提供的运输服务类型。因特网(更一般的是TCP/IP网络)为应用程序提供两个运输层协议&#xff0c;即UDP和TCP。当软件开发者为因特网创建一个新的应用时&#xff0c;首先要做出的决定是&…

js逆向案例 | 加速乐反爬逆向

前言 加速乐作为一种常见的反爬虫技术&#xff0c;在网络上已有大量详尽深入的教程可供参考。然而&#xff0c;对于那些初次接触的人来说&#xff0c;直接面对它可能仍会感到困惑。 声明 本文仅用于学习交流&#xff0c;学习探讨逆向知识&#xff0c;欢迎私信共享学习心得。如…

收银系统源码-商品报损管理

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

ESXi6.7 update 3主机实现新硬件运行老环境

server 2003 SQL server 2000 SQL SP4 vmware tools 一、适用场景 1、运行多年的老企业&#xff0c;积累的数据量庞大&#xff0c;其中的数据库并不一定都是现在开发的平台或系统&#xff0c;而是已经正在运行&#xff0c;不能停业务的状态。 2、老系统老应用平台&#xf…

day01:项目概述,环境搭建

文章目录 软件开发整体介绍软件开发流程角色分工软件环境 外卖平台项目介绍项目介绍定位功能架构 产品原型技术选型 开发环境搭建整体结构&#xff1a;前后端分离开发前后端混合开发缺点前后端分离开发 前端环境搭建Nginx 后端环境搭建熟悉项目结构使用Git进行版本控制数据库环…

Day06-01-lvs

Day06-01-lvs 0. 核心内容1.负载均衡项目 选择故障: 2.lvs 预备姿势-arp3.lvs 概述4. lvs工作模式4.1 预备姿势4.2 lvs-dr模式4.3 lvs-nat模式4.4 小结 5. lvs-dr模式5.1 环境准备5.2 lvs-dr模式配置流程1) lvs服务端配置2) web服务器 RS服务端配置3) 小结4) 调试 5.3 抓包查看…

电脑清理软件用哪个好?这款工具有些饱受争议

电脑清理软件用哪个好?电脑作为我们工作和娱乐的重要工具&#xff0c;其运行速度和安全性直接影响着我们的生活质量。然而&#xff0c;随着时间的推移&#xff0c;电脑系统会积累大量垃圾文件、注册表错误、恶意软件等&#xff0c;导致电脑运行缓慢甚至崩溃。 这时&#xff0c…

el-tree 获取当前勾选节点的选中状态以及选中值对象 触发check-change多次事件问题原因

1.需求 现在需要一个树状结构的资产树 但是现在需求是 获取当前选中的值的状态是选中还是取消选中 然后再用当前选中 or 取消选中的值 进行 选中 or 取消选中的操作 一开始使用的是 check-change 方法 接收参数如图 但是我勾选父节点 或者 子节点后 他会打印一堆数据 是因…

基于Java+SpringMvc+Vue技术的智慧校园系统设计与实现

博主介绍&#xff1a;硕士研究生&#xff0c;专注于信息化技术领域开发与管理&#xff0c;会使用java、标准c/c等开发语言&#xff0c;以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年&#xff0c;拥有近12年的管理工作经验&#xff0c;拥有较丰富的技术架…

昇思25天学习打卡营第11天 | LLM原理和实践:基于MindSpore实现BERT对话情绪识别

1. 基于MindSpore实现BERT对话情绪识别 1.1 环境配置 # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下面mindspore的版本号 !pip uninstall mindspore -y !pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore2.2…

geospy.AI 根据图片定位地理位置

文章目录 简介场景标志性建筑平凡的商店名标志性的物品标志性的地理位置标志性的街道难以分辨的古建筑不出名的山水 简介 GeoSpy.ai 作为一个地理空间情报平台&#xff0c;可以在以下场景中使用&#xff1a; 农业&#xff1a;监控农作物生长情况&#xff0c;预测产量&#xf…

课设:二手车交易管理系统(Java+MySQL)

简易数据库课程设计~分享 技术栈 本项目使用以下技术栈构建&#xff1a; Java: 作为主要编程语言&#xff0c;负责业务逻辑的实现。MySQL: 用于数据存储&#xff0c;管理用户、车辆和订单信息。JDBC: 用于Java与MySQL数据库之间的连接和操作。Swing GUI: 提供用户图形界面&am…

数据库课设---酒店管理系统(MySQL、VBNet)

目录 一. 知识技术 二. 需求分析 2.1 功能需求 2.2 数据需求 三. 数据流图与数据字典 3.1 数据流图 3.1.1 业务流图 3.1.2 数据流图 3.1.3 关系图 3.2 数据字典 四. 数据库设计 4.1 概念模型设计 4.2 逻辑模型设计 4.3 数据库实现 …

【LSB图像低位隐写】字符串隐写

按照自己的理解写了一个简单的字符串隐藏在图像中的python代码 前言 脱胎于内容安全的大作业~ 目前第一阶段&#xff0c;只完成了字符串隐藏在图像中 步过图像隐藏在图像应该异曲同工&#xff0c;之后实现~ 一、代码 图像的output路径和input路径写死了&#xff0c;这个需要…

【SpringBoot】IDEA查看spring bean的依赖关系

前因&#xff1a;研究springcloud config组件时&#xff0c;我发现config-server包下的EnvironmentController不在扫描的包路径下却可以响应客户端的请求&#xff0c;这引起了我的注意&#xff0c;我的问题是&#xff1a;EnvironmentController是怎么被添加进bean工厂的。本章就…

联系表单提交Contact Form自动发送邮件源码

联系表单Contact Form提交后自动发送邮件源码构建指南&#xff1f; 无论是商业网站、博客还是个人主页&#xff0c;几乎每个网站都会有一个联系表单&#xff0c;用于收集用户的反馈、询问或建议。AokSend将探讨联系表单在网站中的重要性&#xff0c;以及如何通过源码实现自动发…

新加坡工作和生活指北:工作篇

文章首发于公众号&#xff1a;Keegan小钢 一年多以前&#xff08;2022 年 8 月初&#xff09;&#xff0c;那时我过来新加坡才 4 个多月&#xff0c;就写了篇文章分享了当时在新加坡的生活和工作体验。文章得到的反响不错&#xff0c;但也反馈出了一些新的问题&#xff0c;比如…

【数据结构】栈的实现(含详细代码)

文章目录 1.栈1.1 栈的概念及结构1.2 栈的实现1.3 代码实现 1.栈 1.1 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守先进后…

如何监控和优化 PostgreSQL 中的连接池使用?

文章目录 一、连接池的基本概念二、监控 PostgreSQL 连接池使用的重要性&#xff08;一&#xff09;性能优化&#xff08;二&#xff09;资源管理&#xff08;三&#xff09;故障排查 三、PostgreSQL 连接池监控指标&#xff08;一&#xff09;活跃连接数&#xff08;二&#x…

下一代 CSS 框架:Mojo CSS

前言 Tailwind CSS 推出即受到广大开发者的欢迎&#xff0c;当前 Github star 数已达 77.8k。它是一个功能类优先&#xff08;utility-first&#xff09;的 CSS 框架&#xff0c;它提供了一系列功能类&#xff0c;让开发者可以在 HTML 中通过组合这些功能类&#xff08;原子类…