当前位置: 首页 > news >正文

solidity高阶 -- 调用接口合约

        在区块链开发中,Solidity 是一种广泛使用的智能合约编程语言,而接口合约(Interface)是 Solidity 中一个非常重要的概念。它为智能合约之间的交互提供了一种标准化的方式,使得合约之间的调用更加灵活、安全且易于管理。本文将深入探讨 Solidity 中接口合约的概念、作用以及具体的实现示例。

         注意:使用继承时请确保代码的正确性,以防丢失个人财产,在这里友情提示您,不要复制来源不明的solidity代码并进行部署。本文为自己梳理总结,如有不足还请指出,感谢包容。 

        学习更多solidity知识请访问 Github -- solidity基础 ,更多实例在 Smart contract

 

二、接口合约的作用

(一)抽象化合约交互

        接口合约将合约的调用逻辑与实现细节分离,使得合约之间的交互更加抽象化。开发者只需要关注接口的定义,而无需关心目标合约的具体实现。这种抽象化的方式使得合约之间的耦合度降低,提高了代码的可维护性和可扩展性。

        例如,假设我们有一个 Counter 合约,它实现了 ICounter 接口。其他合约可以通过 ICounter 接口调用 Counter 合约的函数,而无需知道 Counter 合约的具体实现细节。

(二)提高代码复用性

        接口合约可以被多个合约实现,从而实现代码的复用。多个合约可以共享同一个接口定义,而每个合约可以根据自己的需求实现接口中的函数。这种方式避免了重复编写类似的函数逻辑,提高了开发效率。

(三)增强安全性

        接口合约提供了一种明确的调用规范,使得合约之间的交互更加安全。通过接口合约,调用方可以明确知道目标合约提供的函数签名和返回值类型,从而避免因调用错误而导致的安全问题。同时,接口合约还可以限制调用方对目标合约的访问权限,进一步增强合约的安全性。

 

三、接口合约的实现示例

为了更好地理解接口合约的作用,我们通过一个具体的示例来展示如何使用接口合约。

(一)定义接口合约

首先,我们定义一个接口合约 ICounter,它包含两个函数:count()inc()

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;interface ICounter {function count() external view returns (uint);function inc() external;
}

(二)实现接口合约

        接下来,我们定义一个 Counter 合约,它实现了 ICounter 接口。Counter 合约包含一个状态变量 count,以及两个函数:inc()dec()。其中,inc() 函数用于增加 count 的值,dec() 函数用于减少 count 的值。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;contract Counter {uint public count;function inc() external {count += 1;}function dec() external {count -= 1;}
}

(三)调用接口合约

最后,我们定义一个 CallInterface 合约,它通过 ICounter 接口调用 Counter 合约的函数。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;contract CallInterface {uint public count;function examples(address _counter) external {ICounter(_counter).inc();count = ICounter(_counter).count();}
}

        在 CallInterface 合约中,examples() 函数接收一个合约地址 _counter,并通过 ICounter(_counter) 将该地址转换为 ICounter 类型。然后,调用 ICounter 接口的 inc() 函数来增加 Counter 合约的 count 值,并通过 count() 函数获取当前的 count 值,将其存储在 CallInterface 合约的 count 状态变量中。

 

四、接口合约与抽象合约的区别

        在 Solidity 中,除了接口合约,还有一种类似的合约类型——抽象合约。抽象合约和接口合约有一些相似之处,但也有明显的区别。

(一)定义方式

  • 接口合约:以关键字 interface 开始,函数声明必须是 external 类型,不能包含状态变量。

  • 抽象合约:以关键字 contract 开始,可以包含 externalinternal 函数,也可以包含状态变量。

(二)实现方式

  • 接口合约:接口合约中的函数必须由实现合约提供具体实现,且不能包含任何逻辑。

  • 抽象合约:抽象合约中的函数可以是抽象函数(没有实现),也可以是具体实现的函数。实现合约可以选择实现抽象函数,也可以直接继承抽象合约中的具体实现。

(三)使用场景

  • 接口合约:主要用于定义合约之间的交互规范,使得合约之间的调用更加标准化和抽象化。

  • 抽象合约:主要用于提供一组通用的函数和状态变量,供其他合约继承和扩展。抽象合约可以包含部分实现逻辑,使得继承合约可以复用这些逻辑。

五、关键注意事项

  1. 严格签名匹配:包括参数类型、返回值、可见性(external必须严格一致)

  2. 版本兼容:需使用相同Solidity编译器版本

  3. 限制特性

    • 不能包含构造函数

    • 不能定义状态变量

    • 不能继承其他合约

  4. 返回处理:view函数通过返回值获取数据,非view函数通过事件监听状态变化

 

六、典型应用场景

  1. 代币交互:ERC20标准接口

  2. 预言机调用:数据请求标准化

  3. 可升级合约:通过接口指向不同实现

  4. 合约检测:通过接口判断合约功能支持性

 

七、开发实践建议

  1. 接口命名使用"I"前缀(如ICounter

  2. 为每个功能模块定义独立接口

  3. 使用TypeChain等工具自动生成TypeScript类型定义

  4. 结合require语句进行接口支持检测:

    require(Counter(_counter).supportsInterface(type(ICounter).interfaceId),"Unsupported interface"
    );

八、本文代码总结

接口合约ICounter// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;contract Counter {uint public count;function inc() external {count += 1;}function dec() external {count -= 1;}}
//调用接口合约// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;interface ICounter {function count() external view returns (uint);function inc() external;
}
//interface开头,名字大写,完成了接口调用的方法
//调用了两个合约的函数contract CallInterface {uint public count;function examples(address _counter) external {ICounter(_counter).inc();count = ICounter(_counter).count();}
}
//调用inc这个方法
// count = ICounter(_counter).count();

 

结语

        接口合约如同智能合约世界的通信协议,通过定义清晰的交互边界,极大地提升了合约系统的可维护性和扩展性。当您下次需要实现跨合约调用时,不妨先设计好接口规范——这如同为合约间的对话制定语法规则,将使您的DApp架构更加优雅稳健。

        通过文中的Counter示例实践可以发现,接口合约将功能声明与具体实现分离,既保证了核心逻辑的安全性,又为后续功能扩展保留了充足的灵活性。这正是区块链智能合约开发中"合约优先"设计理念的生动体现。

 

相关文章:

solidity高阶 -- 调用接口合约

在区块链开发中,Solidity 是一种广泛使用的智能合约编程语言,而接口合约(Interface)是 Solidity 中一个非常重要的概念。它为智能合约之间的交互提供了一种标准化的方式,使得合约之间的调用更加灵活、安全且易于管理。…...

若依框架使用(低级)

克隆源码 浏览器搜索若依,选择 RuoYi-Vue RuoYi-Vue RuoYi-Vue 重要的事情说三遍,进入gitee 下面这个页面(注意红色框起来的部分) 进入Gitee进行下载 我下载的是最新的springboot3 下载好后我们可以选择一个文件夹&#xff0…...

找不到 MSVCP120.dll

msvcr120.dll msvcr120.dll 是 Microsoft Visual C Redistributable 的一部分,属于 Visual Studio 2013(VC 12.0)的运行时组件。它的重要性取决于你运行的应用程序是否需要它。 重要性 依赖库:如果某个程序是用 Visual Studio 2…...

AI软件栈:LLVM分析(三)

LLVM IR 文章目录 CFG线性IR 主要采用CFG与线性IR组合描述 CFG *关键在于基本块(Basic Block)的定义 线性IR *关键来自于SSA,单静态赋值...

openwebui入门

1 简介 ‌Open WebUI‌(网址是openwebui.com)是一个高度可扩展、功能强大且用户友好的自托管Web用户界面,专为完全离线操作设计,编程语言是python。它支持对接Ollama和OpenAI兼容的API的大模型。‌ Open WebUI‌在架构上是一种中…...

Spark--如何理解RDD

1、概念 rdd是对数据集的逻辑表示,本身并不存储数据,只是封装了计算逻辑,并构建执行计划,通过保存血缘关系来记录rdd的执行过程和历史(当一个rdd需要重算时,系统会根据血缘关系追溯到最初的数据源&#xff…...

CTFSHOW-WEB入门-PHP特性89-100

题目:web 89 题目:解题思路:这道题目涉及了两个函数:preg_match()和intval()简要介绍一下两个函数 preg_match()用于对字符串进行正则表达式的匹配&#xff0…...

[250204] Mistral Small 3:小巧、快速、强大 | asdf 0.16.0 发布:Golang 重写带来性能飞跃

目录 Mistral AI 发布开源模型 Mistral Small 3:小巧、快速、强大asdf 0.16.0 版本发布:Golang 重写带来性能飞跃! Mistral AI 发布开源模型 Mistral Small 3:小巧、快速、强大 法国人工智能初创公司 Mistral AI 发布了最新的开源…...

PySpark学习笔记5-SparkSQL

sparkSql的数据抽象有两种。 一类是data set适用于java和Scala 一类是data frame适用于java,Scala,python 将r d d转换为data frame #方式一 df spark.createDataFrame(rdd,schema[name,age]) #方式二 schema Structtype(). add(id,integertype(),nu…...

windows版的docker如何使用宿主机的GPU

windows版的docker使用宿主机的GPU的命令 命令如下 docker run -it --nethost --gpus all --name 容器名 -e NVIDIA_DRIVER_CAPABILITIEScompute,utility -e NVIDIA_VISIBLE_DEVICESall 镜像名效果 (transformer) rootdocker-desktop:/# python Python 3.9.0 (default, Nov 15 …...

Python爬虫:1药城店铺爬虫(完整代码)

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…...

代码随想录算法训练营打卡第55天:并查集相关问题;

Java并查集的模板 //并查集模板 class DisJoint{private int[] father;public DisJoint(int N) {father new int[N];for (int i 0; i < N; i){father[i] i;}}public int find(int n) {return n father[n] ? n : (father[n] find(father[n]));}public void join (int …...

K8S学习笔记-------1.安装部署K8S集群环境

1.修改为root权限 #sudo su 2.修改主机名 #hostnamectl set-hostname k8s-master01 3.查看网络地址 sudo nano /etc/netplan/01-netcfg.yaml4.使网络配置修改生效 sudo netplan apply5.修改UUID&#xff08;某些虚拟机系统&#xff0c;需要设置才能生成UUID&#xff09;#…...

云原生周刊:K8s引领潮流

开源项目推荐 KWOK KWOK&#xff08;Kubernetes WithOut Kubelet&#xff09;是一个开源项目&#xff0c;旨在提供一个轻量级的 K8s 集群模拟环境&#xff0c;允许用户在不依赖真实节点的情况下&#xff0c;本地模拟整个 K8s 集群。它通过模拟 Kubelet 和其他集群组件的行为&…...

C_位运算符及其在单片机寄存器的操作

C语言的位运算符用于直接操作二进制位&#xff0c;本篇简单结束各个位运算符的作业及其在操作寄存器的应用场景。 一、位运算符的简单说明 1、按位与运算符&#xff08;&&#xff09; 功能&#xff1a;按位与运算符对两个操作数的每一位执行与操作。如果两个对应的二进制…...

【算法篇】贪心算法

目录 贪心算法 贪心算法实际应用 一&#xff0c;零钱找回问题 二&#xff0c;活动选择问题 三&#xff0c;分数背包问题 将数组和减半的最小操作次数 最大数 贪心算法 贪心算法&#xff0c;是一种在每一步选择中都采取当前状态下的最优策略&#xff0c;期望得到全局最优…...

Selenium 浏览器操作与使用技巧——详细解析(Java版)

目录 一、浏览器及窗口操作 二、键盘与鼠标操作 三、勾选复选框 四、多层框架/窗口定位 五、操作下拉框 六、上传文件操作 七、处理弹窗与 alert 八、处理动态元素 九、使用 Selenium 进行网站监控 前言 Selenium 是一款非常强大的 Web 自动化测试工具&#xff0c;能够…...

ioDraw桌面版 v3.4.0发布!AI文生图,AI图生图,手绘风格一键转换!

流程图功能升级 AI 文生图&#xff1a; 用户现在能输入文字描述&#xff0c;让软件自动生成对应的流程图画面&#xff0c;减少了手动绘图的工作量&#xff0c;提高创作效率&#xff0c;比如输入 “项目开发流程”&#xff0c;软件可能就会生成包含需求分析、设计、开发、测试…...

深入理解Node.js_架构与最佳实践

1. 引言 1.1 什么是Node.js Node.js简介:Node.js是一个基于Chrome V8引擎的JavaScript运行时,用于构建快速、可扩展的网络应用。Node.js的历史背景和发展:Node.js最初由Ryan Dahl在2009年发布,旨在解决I/O密集型应用的性能问题。随着时间的推移,Node.js社区不断壮大,提供…...

安装和卸载RabbitMQ

我的飞书:https://rvg7rs2jk1g.feishu.cn/docx/SUWXdDb0UoCV86xP6b3c7qtMn6b 使用Ubuntu环境进行安装 一、安装Erlang 在安装RabbitMQ之前,我们需要先安装Erlang,RabbitMQ需要Erlang的语言支持 #安装Erlang sudo apt-get install erlang 在安装的过程中,会弹出一段信息,此…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...